【问题标题】:Jasmine unit test fails when spying on a service method监视服务方法时茉莉花单元测试失败
【发布时间】:2015-04-05 23:50:35
【问题描述】:

我有一个 Angular 模块,validation,声明如下:

(function(ns){
    ns.validation = angular.module("validation", []);
})(blog);

模块包含两个服务validator和validationRulesProvider,看起来像:

(function(module){
    module
    .factory("validationRulesProvider", function(){

        var _getRules = function() {
            return [{
                isValid: function(post) {
                    return post.length > 0;
                }
            }];
        };

        return {
            getRules: _getRules
        };

    });
})(blog.validation);

(function(module){
    module
    .factory("validator", ["validationRulesProvider", function(validationRulesProvider){

        var _validate = function(post) {
            var rules = validationRulesProvider.getRules();
            for (var rule in rules) {
                if (!rule.isValid(post)) {
                    return false;
                }
            }
            return true;
        };

        return {
            validate: _validate
        };

    }]);
})(blog.validation);

我正在尝试测试(使用 Jasmine)

  • validationRulesProvider 上的 getRules 方法实际上是从 validate 方法中调用的
  • post 参数贯穿从所述方法返回的每个规则

我有以下 Jasmine 测试脚本:

describe("Validator: ", function(){

var _validator;
var _mockedValidationRulesProvider;
var _mockRule;

beforeEach(function(){

    module("validation");

    inject(function(validationRulesProvider){
        _mockedValidationRulesProvider = validationRulesProvider;
    });

    _mockRule = jasmine.createSpy();

    spyOn(_mockedValidationRulesProvider, "getRules")
    .and
    .returnValue([{
        isValid: _mockRule
    }]);

    inject(function(validator){
        _validator = validator;
    });

});

describe("getRules - ", function(){

    it("gets a collection of rules from the rules provider", function(){
        _validator.validate("");
        expect(_mockedValidationRulesProvider.getRules).toHaveBeenCalled();
    });

    it("should pass the post through each rule received from the rules provider", function(){
        expect(_mockRule.calls.count()).toEqual(_mockedValidationRulesProvider.getRules().length);
    });

});

});

所以,我只是想创建一个validationRulesProvider.getRules 的假实现。我的麻烦是这两个测试都失败了。如果我改变这条线:

    spyOn(_mockedValidationRulesProvider, "getRules")
    .and
    .returnValue([{
        isValid: _mockRule
    }]);

简单地说

    spyOn(_mockedValidationRulesProvider, "getRules")
    .and
    .returnValue([]);

然后两个测试中的第一个通过,因为验证器.validate 中的循环永远不会进入。

Karma 给出以下输出:

PhantomJS 1.9.8 (Windows 7) 验证器:getRules - 从规则提供程序获取规则集合 FAILED TypeError:“未定义”不是函数(评估“rule.isValid(post)”) 在 C:/Users/User/JS/Angular/Learning/blogsite/scripts/validation/validator.js:8 在 C:/Users/User/JS/Angular/Learning/blogsite/scripts/tests/validator.test.js:32 PhantomJS 1.9.8 (Windows 7) Validator: getRules - 应该通过从规则提供者 FAILED 收到的每个规则传递帖子 预期 0 等于 1。 在 C:/Users/User/JS/Angular/Learning/blogsite/scripts/tests/validator.test.js:37 PhantomJS 1.9.8(Windows 7):执行 5 次,共 5 次(2 次失败)(0 秒 / 0.039 秒)

对于为什么测试在第一个实例中失败,我有点茫然,因为看起来我应该从间谍返回的是一个包含“isValid”函数的对象数组 - 这是正是从该函数的实际实现返回的内容。

我做错了什么?

【问题讨论】:

  • @yazaki 解决了我的一个问题,另一个是我在第二个单元测试中实际上没有调用被测方法。我是个白痴。

标签: javascript angularjs unit-testing mocking jasmine


【解决方案1】:

当你想在javascript中循环一个数组时,你需要使用javascript basic 'for loop'而不是'for-in loop'

验证器工厂中的代码应该是这样的。

for (var i = 0; i < rules.length; i++) {
    var rule = rules[i];
    if (!rule.isValid(post)) {
        return false;
    }
}

【讨论】:

  • 第一个测试通过了,谢谢。我对 JS 很陌生,所以我尝试使用 for...in like for each。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-13
  • 2016-07-13
  • 2017-09-27
相关资源
最近更新 更多