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
.
精彩评论