茉莉花单元测试出乎意料这个参考
Jasmine Unit Tests Unexpected this Reference
我正在尝试在 Jasmine 中测试一个相当简单的 JavaScript 函数,但是第一条语句因未定义而抛出错误。
myClass.prototype.functiontoBeTested = function() {
var x = this.method()
...
}
上面在 Jasmine 中抛出一个错误,因为 method
不是一个函数并且是未定义的。早些时候修改了原型以使用此方法,出于好奇,我在规范本身中将此方法分配给了我的测试对象:
myObject.method = function(){return mockResults;};
所以我决定将 this
记录到控制台,而不是它成为我的对象,我看到 Window {top: Window, location: Location, document: document, window: Window, external: Object…}
这似乎不正确。我之前在 Jasmine 中测试一个使用 this
的函数时遇到过这个问题,但只是更改了源代码以按名称引用对象,因为该函数被分配给了闭包中的某些东西。在这种情况下我不能那样做,我很好奇为什么 this
指的是意想不到的事情(至少对我而言)。
编辑:关于测试用例的一些细节,如所要求的那样:
it("updates the control count", function(){
var mockResults = { ... };
myObject.method = function() {return mockResults;};
expect(myObject.method).not.toThrow();
});
现在我只是想让方法在测试期间执行到完成。要测试的函数会更新某些 HTML 组件上的文本,一旦我可以将其实际 运行,我将着手验证这些内容。导致错误的方法是函数的第一行,它只是被调用对象的访问器方法。在实际执行中,var x = this.method()
运行s没有问题。在 jasmine 中测试时 var x = this.method()
会抛出一个错误,因为 method()
对于 this
是未定义的。它不是 this
引用调用对象,而是引用 window。这不会在现场发生,而只会在使用 Jasmine 进行测试时发生。即使我在上述测试中执行之前为测试对象强行定义了该方法,该方法也是未定义的。就在那时,我决定将 this
登录到源代码中的控制台,并意识到它并不是指我所期望的。
在 JavaScript this
中,方法取决于调用它的上下文。当您调用 myObject.method()
时,method
是从 myObject
的上下文中调用的,因此 this
是 myObject
.
当您将函数传递给 Jasmine toThrow
匹配器时,它会在传递时调用它 (see source code):
try {
actual();
} catch (e) {
// ....
}
这里,actual()
是调用你的方法。它没有任何特定的上下文,因此默认情况下它将从 window
上下文中调用。
解决方案是明确地 bind 你 method
到 myObject
像下面这样:
expect(myObject.method.bind(myObject)).not.toThrow();
问题的致谢,您可以在那里找到更多详细信息:
- Does Jasmine's toThrow matcher require the argument to be wrapped in an anonymous function?
- How to write a test which expects an Error to be thrown in Jasmine?
我正在尝试在 Jasmine 中测试一个相当简单的 JavaScript 函数,但是第一条语句因未定义而抛出错误。
myClass.prototype.functiontoBeTested = function() {
var x = this.method()
...
}
上面在 Jasmine 中抛出一个错误,因为 method
不是一个函数并且是未定义的。早些时候修改了原型以使用此方法,出于好奇,我在规范本身中将此方法分配给了我的测试对象:
myObject.method = function(){return mockResults;};
所以我决定将 this
记录到控制台,而不是它成为我的对象,我看到 Window {top: Window, location: Location, document: document, window: Window, external: Object…}
这似乎不正确。我之前在 Jasmine 中测试一个使用 this
的函数时遇到过这个问题,但只是更改了源代码以按名称引用对象,因为该函数被分配给了闭包中的某些东西。在这种情况下我不能那样做,我很好奇为什么 this
指的是意想不到的事情(至少对我而言)。
编辑:关于测试用例的一些细节,如所要求的那样:
it("updates the control count", function(){
var mockResults = { ... };
myObject.method = function() {return mockResults;};
expect(myObject.method).not.toThrow();
});
现在我只是想让方法在测试期间执行到完成。要测试的函数会更新某些 HTML 组件上的文本,一旦我可以将其实际 运行,我将着手验证这些内容。导致错误的方法是函数的第一行,它只是被调用对象的访问器方法。在实际执行中,var x = this.method()
运行s没有问题。在 jasmine 中测试时 var x = this.method()
会抛出一个错误,因为 method()
对于 this
是未定义的。它不是 this
引用调用对象,而是引用 window。这不会在现场发生,而只会在使用 Jasmine 进行测试时发生。即使我在上述测试中执行之前为测试对象强行定义了该方法,该方法也是未定义的。就在那时,我决定将 this
登录到源代码中的控制台,并意识到它并不是指我所期望的。
在 JavaScript this
中,方法取决于调用它的上下文。当您调用 myObject.method()
时,method
是从 myObject
的上下文中调用的,因此 this
是 myObject
.
当您将函数传递给 Jasmine toThrow
匹配器时,它会在传递时调用它 (see source code):
try {
actual();
} catch (e) {
// ....
}
这里,actual()
是调用你的方法。它没有任何特定的上下文,因此默认情况下它将从 window
上下文中调用。
解决方案是明确地 bind 你 method
到 myObject
像下面这样:
expect(myObject.method.bind(myObject)).not.toThrow();
问题的致谢,您可以在那里找到更多详细信息:
- Does Jasmine's toThrow matcher require the argument to be wrapped in an anonymous function?
- How to write a test which expects an Error to be thrown in Jasmine?