dimanche 5 avril 2015

Jasmine unit test fails when spying on a service method

I have an Angular module, validation, which is declared like so:



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


The module contains two services, validation and validationRulesProvider, which look like:



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

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

return {
getRules: _getRules
};

});
})(blog.validation);


and



(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);


I am attempting to test (using Jasmine) that



  • The getRules method on validationRulesProvider is actually called from the validate method

  • The post parameter is run through each rule returned from said method


I have the following Jasmine test script:



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);
});

});

});


So, I'm simply trying to create a fake implementation of validationRulesProvider.getRules. My trouble is that both of these tests fail. If I alter the line:



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


to simply be



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


then the first of the two tests pass, as the loop in validator.validate will never be entered.


Karma gives the following output:



PhantomJS 1.9.8 (Windows 7) Validator: getRules - gets a collection of rules from the rules provider FAILED TypeError: 'undefined' is not a function (evaluating 'rule.isValid(post)') at C:/Users/User/JS/Angular/Learning/blogsite/scripts/validation/validator.js:8 at C:/Users/User/JS/Angular/Learning/blogsite/scripts/tests/validator.test.js:32 PhantomJS 1.9.8 (Windows 7) Validator: getRules - should pass the post through each rule received from the rules provider FAILED Expected 0 to equal 1. at C:/Users/User/JS/Angular/Learning/blogsite/scripts/tests/validator.test.js:37 PhantomJS 1.9.8 (Windows 7): Executed 5 of 5 (2 FAILED) (0 secs / 0.039 secs)



I'm a bit of a loss as to why the tests are failing in the first instance because it seems like what I should be returning from the spy is an array of one object which contains an "isValid" function - which is exactly what is returned from the actual implementation of that function.


What am I doing wrong?


Aucun commentaire:

Enregistrer un commentaire