Javascript 使用Jasmine在CoffeeScript中测试Backbone.js时出现类型错误
我目前正在处理这个问题,但试图用CoffeeScript而不是纯JavaScript来编写它 到目前为止还不错,但当我尝试对代码运行Jasmine测试时,遇到了一些类型错误:Javascript 使用Jasmine在CoffeeScript中测试Backbone.js时出现类型错误,javascript,backbone.js,coffeescript,jasmine,Javascript,Backbone.js,Coffeescript,Jasmine,我目前正在处理这个问题,但试图用CoffeeScript而不是纯JavaScript来编写它 到目前为止还不错,但当我尝试对代码运行Jasmine测试时,遇到了一些类型错误: TypeError: Cannot call method 'isFirstTrack' of undefined TypeError: Cannot call method 'get' of undefined 我的CoffeeScript/Backbone文件如下所示: jQuery -> class wi
TypeError: Cannot call method 'isFirstTrack' of undefined
TypeError: Cannot call method 'get' of undefined
我的CoffeeScript/Backbone文件如下所示:
jQuery ->
class window.Album extends Backbone.Model
isFirstTrack: (index) ->
index is 0
class window.AlbumView extends Backbone.View
tagName: 'li'
className: 'album'
initialize: ->
@model.bind('change', @render)
@template = _.template $('#album-template').html()
render: =>
renderedContent = @template @model.toJSON()
$(@el).html(renderedContent)
return this
var albumData = [{
"title": "Album A",
"artist": "Artist A",
"tracks": [
{
"title": "Track A",
"url": "/music/Album A Track A.mp3"
},
{
"title": "Track B",
"url": "/music/Album A Track B.mp3"
}]
}, {
"title": "Album B",
"artist": "Artist B",
"tracks": [
{
"title": "Track A",
"url": "/music/Album B Track A.mp3"
},
{
"title": "Track B",
"url": "/music/Album B Track B.mp3"
}]
}];
describe("Album", function () {
beforeEach(function () {
album = new Album(albumData[0]);
});
it("creates from data", function () {
expect(this.album.get('tracks').length).toEqual(2);
});
describe("first track", function() {
it("identifies correct first track", function() {
expect(this.album.isFirstTrack(0)).toBeTruthy();
})
});
});
茉莉花测试规范如下:
jQuery ->
class window.Album extends Backbone.Model
isFirstTrack: (index) ->
index is 0
class window.AlbumView extends Backbone.View
tagName: 'li'
className: 'album'
initialize: ->
@model.bind('change', @render)
@template = _.template $('#album-template').html()
render: =>
renderedContent = @template @model.toJSON()
$(@el).html(renderedContent)
return this
var albumData = [{
"title": "Album A",
"artist": "Artist A",
"tracks": [
{
"title": "Track A",
"url": "/music/Album A Track A.mp3"
},
{
"title": "Track B",
"url": "/music/Album A Track B.mp3"
}]
}, {
"title": "Album B",
"artist": "Artist B",
"tracks": [
{
"title": "Track A",
"url": "/music/Album B Track A.mp3"
},
{
"title": "Track B",
"url": "/music/Album B Track B.mp3"
}]
}];
describe("Album", function () {
beforeEach(function () {
album = new Album(albumData[0]);
});
it("creates from data", function () {
expect(this.album.get('tracks').length).toEqual(2);
});
describe("first track", function() {
it("identifies correct first track", function() {
expect(this.album.isFirstTrack(0)).toBeTruthy();
})
});
});
我猜问题与CoffeeScript将所有内容包装在函数中有关。当我从等式中删除jQuery时,它工作得很好。
奇怪的是,即使Jasmine告诉我
TypeError:如果我在控制台的页面上运行album.isFirstTrack(0)
,它返回true
,那么窗口确实可以访问变量和方法。原因是作用域,是的
在声明不带var
关键字的album
变量且不将其附加到另一个对象时,您正在全局范围内创建一个变量
这是个坏主意。您确实希望限制创建的全局对象的数量,因为另一块javascript很容易覆盖您的数据,或导致冲突等
从这个角度来看,您在测试中调用this.model
的想法是正确的。问题是,您需要将模型
附加到此
才能执行此操作。很简单:
beforeEach(function () {
this.album = new Album(albumData[0]);
});
你所要做的就是说this.album=…
,你就完成了。现在,您的测试将能够找到此相册,并且一切都应该正常。原因在于范围,是的
在声明不带var
关键字的album
变量且不将其附加到另一个对象时,您正在全局范围内创建一个变量
这是个坏主意。您确实希望限制创建的全局对象的数量,因为另一块javascript很容易覆盖您的数据,或导致冲突等
从这个角度来看,您在测试中调用this.model
的想法是正确的。问题是,您需要将模型
附加到此
才能执行此操作。很简单:
beforeEach(function () {
this.album = new Album(albumData[0]);
});
你所要做的就是说this.album=…
,你就完成了。现在,您的测试将能够找到此相册,并且一切都应该正常。(注意:我相信Derick的答案是正确的,它解释了类型错误:无法调用未定义的消息的方法'isFirstTrack',但此答案也可能是相关的。)
你说
当我从等式中删除jQuery时,它工作得很好
也就是说,如果你删掉了jQuery->
,那么你的测试通过了吗?如果是这样,那就不是范围问题;这是一个代码顺序问题。当您将函数传递给jQuery时,在文档准备就绪之前不会执行该函数。同时,您的测试在定义相册
和相册视图
类之前立即运行
没有理由使用jQuery->
包装器,因为您的类定义不依赖于任何现有的DOM元素。(注意:我相信Derick的回答是正确的,它解释了类型错误:无法调用未定义的消息的方法'isFirstTrack',但这个答案也可能是相关的。)
你说
当我从等式中删除jQuery时,它工作得很好
也就是说,如果你删掉了jQuery->
,那么你的测试通过了吗?如果是这样,那就不是范围问题;这是一个代码顺序问题。当您将函数传递给jQuery时,在文档准备就绪之前不会执行该函数。同时,您的测试在定义相册
和相册视图
类之前立即运行
没有理由使用jQuery->
包装器,因为您的类定义不依赖于任何现有的DOM元素。在深入研究了更多内容之后,我已经设法修复了它。从Jasmine测试规范中的两个expect
语句中删除this
关键字似乎是可行的。我仍然有兴趣理解为什么——这是一个范围问题吗?问题不是CoffeeScript的函数包装器。通过将这两个类定义为window.Album
和window.AlbumView
,您已经正确地导出了这两个类。在深入研究之后,我成功地修复了它。从Jasmine测试规范中的两个expect
语句中删除this
关键字似乎是可行的。我仍然有兴趣理解为什么——这是一个范围问题吗?问题不是CoffeeScript的函数包装器。通过将这两个类定义为window.Album
和window.AlbumView
,您已经正确地导出了这两个类。对,Album=
和this.Album=
是不等价的(除非this
是window
,这不是Jasmine在每次调用回调之前调用的情况)。对,album=
和this.album=
是不等价的(除非this
是window
,Jasmine在每次回调之前调用时就不是这样了)。回答很好,建议也很好。除非jQuery准备就绪时需要运行一些东西,否则jQuery->根本不需要。这是一个很好的答案和一个很好的建议。除非jQuery准备就绪时需要运行某些东西,否则jQuery->根本就不是必需的。