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

Anc*_*ent 13 javascript bdd unit-testing 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 !";
    }
}
Run Code Online (Sandbox Code Playgroud)

现在我想测试茉莉花的toHaveBeenCalled()匹配器.这是我写的

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

但它说 undefined() method does not exist

bas*_*ode 24

看看你的用例,我不推荐toHaveBeenCalled在这里使用.toHaveBeenCalled在需要测试回调(异步)或与模拟组合的情况下非常有用.

考虑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');
 });

});
Run Code Online (Sandbox Code Playgroud)

  • 这是一个很好的答案.感谢您抽出宝贵时间来解释正确的测试方法. (3认同)

Alb*_*gni 17

编辑:查看基本代码答案以获得更好的方法


从文档中,您应该像下面这样使用它:

spyOn(foo, 'setBar');

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

所以你应该写:

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