茉莉花单元测试出乎意料这个参考

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 的上下文中调用的,因此 thismyObject.

当您将函数传递给 Jasmine toThrow 匹配器时,它会在传递时调用它 (see source code):

try {
    actual();
} catch (e) {
   // ....
}

这里,actual()是调用你的方法。它没有任何特定的上下文,因此默认情况下它将从 window 上下文中调用。

解决方案是明确地 bindmethodmyObject 像下面这样:

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?