Jasmine单元测试在监视服务方法时失败

Jasmine unit test fails when spying on a service method

本文关键字:方法 失败 服务 监视 单元测试 Jasmine      更新时间:2023-09-26

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

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

该模块包含两个服务,验证器和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([]);

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

因果报应给出以下输出:

PhantomJS 1.9.8(Windows 7)Validator:getRules-从规则提供程序获取规则集合FAILEDTypeError:"undefined"不是函数(正在计算"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:32PhantomJS 1.9.8(Windows 7)验证程序:getRules-应该通过从规则提供程序收到的每个规则传递帖子FAILED0应等于1。位于C:''Users/User/JS/Angular/Learning/blogsite/scripts/tests/validator.test.JS:37PhantomJS 1.9.8(Windows 7):执行了5个中的5个(2个失败)(0秒/0.039秒)

我有点不明白为什么测试在第一个实例中失败,因为我似乎应该从间谍中返回的是一个包含"isValid"函数的对象数组,这正是从该函数的实际实现中返回的。

我做错了什么?

当您想在javascript中循环数组时,需要使用javascript basic'for-roop',而不是'for-in-roop'

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

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