试图了解Jasmine的toHaveBeenCalled()匹配器

时间:2013-05-28 08:29:04

标签: javascript unit-testing bdd jasmine

我是jasmine的新手,这里是我的src文件,我在其中创建Auth

function Auth() {
}

Auth.prototype.isEmpty = function(str) {
    return (!str || 0 === str.length);
}

Auth.prototype.Login = function (username , password) {
    if (this.isEmpty(username) || this.isEmpty(password)) {
        return "Username or Password cann't be blank ";
    }
    else {
        return "Logged In !";
    }
}

现在我想测试jasmine的toHaveBeenCalled()匹配器。这是我写的

it("should be able to Login", function () {
    spyOn(authobj);
    expect(authobj.Login('abc', 'abc')).toHaveBeenCalled();
});

但它说undefined() method does not exist

3 个答案:

答案 0 :(得分:24)

查看您的用例,我不建议您在此处使用toHaveBeenCalledtoHaveBeenCalled在您需要测试回调(异步)或与模拟组合的情况下非常有用。

Auth.prototype.Login内发生的所有事情视为“外部世界”无法看到的实施细节。您不应该测试实现细节。这触发了两个问题。

为什么我不测试实现细节?

它使重构变得困难。假设您想要Auth.prototype.isEmpty出于某些原因替换underscore.isEmpty。几天后,您决定完全将underscore替换为lodash。这会迫使您改变测试三次。考虑阻止您轻松重构的所有内容,作为“禁止”。

我应该测试什么?

公共API。 “外部世界”可见的一切。在你的情况下“登录!”并且“用户名或密码不能为空”。

这导致3次测试:

describe('Login', function() {

 it('returns "success" string when username and password are not empty', function() {
   expect(new Auth().Login('non-empty', 'non-empty')).toBe('Logged In !');
 });

 it('returns "failure" string when username is empty', function() {
   expect(new Auth().Login('', 'non-empty')).toBe('Username or Password cannot be blank');
 });

 it('returns "failure" string when password is empty', function() {
   expect(new Auth().Login('non-empty', '')).toBe('Username or Password cannot be blank');
 });

});

答案 1 :(得分:17)

编辑:请basecode answer查看更好的方法


From the docs,您应该像以下一样使用它:

spyOn(foo, 'setBar');

it("tracks that the spy was called", function() {
  expect(foo.setBar).toHaveBeenCalled();
});

所以你应该写:

it("should be able to Login", function () {
  spyOn(authobj, 'isEmpty');  
  authobj.Login('abc', 'abc');  
  expect(authobj.isEmpty).toHaveBeenCalled();
});

答案 2 :(得分:0)

它的使用简单,基本上: -

spyOn(<name_of_the_object>, '<name_of_the_method>')

expect(<name_of_the_object>.<name_of_the_method>).toHaveBeenCalled();