开发者

How do I use CoffeeScript to mock out existing code?

I'd like mock out MarkdownDeep, I've the following code, in JavaScript

MarkdownDeep = new (function () {
    this.Markdown = functio开发者_JAVA百科n () {
        this.Transform = function (a) {
            return "html";
        };
    };
})();

but I'm having trouble implementing this in CoffeeScript

I tried the following

MarkdownDeep = new (->
  @Markdown = ->
    @Transform = (a) ->
      "html"
)()
window.MarkdownDeep = MarkdownDeep

but it doesn't work, specifically in my unit test markdown = new MarkdownDeep.Markdown() gives "undefined is not a function", though the JS version mocks out fine.


Your example results in the following javascript code:

var MarkdownDeep;
MarkdownDeep = new (function() {
  return this.Markdown = function() {
    return this.Transform = function(a) {
      return "html";
    };
  };
});
window.MarkdownDeep = MarkdownDeep;

The line return this.Markdown = function() { /* ... */ } makes the function the object returned by the new operator.

Writing

MarkdownDeep = new (->
  @Markdown = ->
    @Transform = (a) ->
      "html"
    return
  return
)
window.MarkdownDeep = MarkdownDeep

fixes the problem.

Addition: This answer mentions the algorithm for object construction in javascript


CoffeeScript's implicit returns can lead to mayhem when used in conjunction with new. As others have pointed out, you could use explicit returns. Another option is to use class, which creates a function (the constructor) with no implicit return:

MarkdownDeep = new class
  constructor: ->
    @Markdown = class
      constructor: ->
        @Transform = (a) ->
          'html'

Of course, that's not very readable in this case, but as a general rule, you'll save yourself headaches by using class whenever you use new.


You need to explicitly set a return value for your objects/classes or else it will return the member functions when creating a new instance.

JS FIDDLE

MarkdownDeep = new (->
  @Markdown = ->
    @Transform = (a) ->
      "html"
    undefined #return undefined instead of this.Transform
  undefined #return undefined instead of this.Markdown
)

markdown = new MarkdownDeep.Markdown()
alert markdown.Transform()

compiles to:

var MarkdownDeep, markdown;
MarkdownDeep = new (function() {
  this.Markdown = function() {
    this.Transform = function(a) {
      return "html";
    };
    return;
  };
  return;
});
markdown = new MarkdownDeep.Markdown();
alert(markdown.Transform());


This is what Coffeescript gives as output

var MarkdownDeep;
MarkdownDeep = new (function() {
  return this.Markdown = function() {
    return this.Transform = function(a) {
      return "html";
    };
  };
});

The last line in every function is implicitly returned in Coffeescript. Checking this in the console yields MarkdownDeep as

function () {
    return this.Transform = function(a) {
        return "html";
    };
}

which returns a function that does not have Markdown() as a method.


CoffeeScript automatically wraps each output file in an anonymous function ((function() { ... })()). To disable this use the --bare or -b option when running coffee.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜