单元测试 spyOn 永远不会被称为 angular 工厂
Unit test spyOn is never called angular factory
我正在尝试为 angular 工厂编写单元测试:
define([], function () {
'use strict';
var factoryName = 'UserFactory';
var components = ['ProductFactory', '$state'];
var factory = function (ProductFactory, $state) {
var viewState = function(view, data) {
if(data.access[view] === true) {
return;
}
else {
$state.go('notAuth');
}
};
return {
viewState: viewState
};
};
components.push(factory);
return {
name: factoryName,
component: components
};
});
我有以下单元测试:
define(['require', 'angular-mocks'], function (require) {
'use strict';
var angular = require('angular');
describe('<-- UserFactory Spec ------>', function () {
var scope, $httpBackend, userFactory;
beforeEach(angular.mock.module('UserFactory'));
beforeEach(inject(function (_$rootScope_, _UserFactory_) {
scope = _$rootScope_.$new();
userFactory = _UserFactory_;
spyOn(userFactory, 'viewState').and.returnValue({firstName:'Joe',lastName:'Smith',access:'read'});
scope.$apply();
}));
it('method viewState() was called', function () {
expect(userFactory.viewState).toHaveBeenCalled();
});
});
});
但是我看到以下错误:
Expected spy viewState to have been called.
如果您尝试测试 viewState
函数的实现,则需要在测试中调用它。您也不需要测试它是否被调用(因为源代码没有测试它)。
你不需要模拟它,这违背了测试它的目的。这是因为模拟 不会 调用实际的实现,除非你告诉它但你在这里不需要它。
您的测试应如下所示:
describe('<-- UserFactory Spec ------>', function () {
var userFactory;
var $state = {
go: function(){}
};
beforeEach(angular.mock.module('UserFactory'));
// Set the $state injectable to be our mocked out $state (only for this test)
beforeEach(module(function ($provide) {
$provide.value('$state', $state);
}));
beforeEach(inject(function (_UserFactory_) {
userFactory = _UserFactory_;
// Mock out the $state.go method
spyOn($state, 'go');
}));
it('should redirect to the notAuth state', function () {
// Call the method we are testing
userFactory.viewState(/** pass in some conditions to make it call $state.go**/);
expect($state.go).toHaveBeenCalledWith('notAuth');
});
});
我在这里做了一些事情:
- 删除了 $scope,这里不需要它。
- 模拟了
$state.go function
- 所以我们可以测试它被调用了。
- 已调用
userFactory.viewState()
- 因此我们可以测试函数。
- 删除了
viewState()
的模拟 - 这样我们就可以测试实际的实现。
要测试它是否正确调用此方法,您可以使用一些 console.logs
.
var viewState = function(view, data) {
console.log('View ', view);
console.log('Data ', data);
console.log(data.access[view]);
console.log(data.access[view] === true);
if(data.access[view] === true) {
return;
}
else {
$state.go('notAuth');
}
};
现在只需检查所有控制台日志是否符合您的预期。
P.S 我无法测试此代码,因此它可能不是 100%,但这是一般要点。
我正在尝试为 angular 工厂编写单元测试:
define([], function () {
'use strict';
var factoryName = 'UserFactory';
var components = ['ProductFactory', '$state'];
var factory = function (ProductFactory, $state) {
var viewState = function(view, data) {
if(data.access[view] === true) {
return;
}
else {
$state.go('notAuth');
}
};
return {
viewState: viewState
};
};
components.push(factory);
return {
name: factoryName,
component: components
};
});
我有以下单元测试:
define(['require', 'angular-mocks'], function (require) {
'use strict';
var angular = require('angular');
describe('<-- UserFactory Spec ------>', function () {
var scope, $httpBackend, userFactory;
beforeEach(angular.mock.module('UserFactory'));
beforeEach(inject(function (_$rootScope_, _UserFactory_) {
scope = _$rootScope_.$new();
userFactory = _UserFactory_;
spyOn(userFactory, 'viewState').and.returnValue({firstName:'Joe',lastName:'Smith',access:'read'});
scope.$apply();
}));
it('method viewState() was called', function () {
expect(userFactory.viewState).toHaveBeenCalled();
});
});
});
但是我看到以下错误:
Expected spy viewState to have been called.
如果您尝试测试 viewState
函数的实现,则需要在测试中调用它。您也不需要测试它是否被调用(因为源代码没有测试它)。
你不需要模拟它,这违背了测试它的目的。这是因为模拟 不会 调用实际的实现,除非你告诉它但你在这里不需要它。
您的测试应如下所示:
describe('<-- UserFactory Spec ------>', function () {
var userFactory;
var $state = {
go: function(){}
};
beforeEach(angular.mock.module('UserFactory'));
// Set the $state injectable to be our mocked out $state (only for this test)
beforeEach(module(function ($provide) {
$provide.value('$state', $state);
}));
beforeEach(inject(function (_UserFactory_) {
userFactory = _UserFactory_;
// Mock out the $state.go method
spyOn($state, 'go');
}));
it('should redirect to the notAuth state', function () {
// Call the method we are testing
userFactory.viewState(/** pass in some conditions to make it call $state.go**/);
expect($state.go).toHaveBeenCalledWith('notAuth');
});
});
我在这里做了一些事情:
- 删除了 $scope,这里不需要它。
- 模拟了
$state.go function
- 所以我们可以测试它被调用了。 - 已调用
userFactory.viewState()
- 因此我们可以测试函数。 - 删除了
viewState()
的模拟 - 这样我们就可以测试实际的实现。
要测试它是否正确调用此方法,您可以使用一些 console.logs
.
var viewState = function(view, data) {
console.log('View ', view);
console.log('Data ', data);
console.log(data.access[view]);
console.log(data.access[view] === true);
if(data.access[view] === true) {
return;
}
else {
$state.go('notAuth');
}
};
现在只需检查所有控制台日志是否符合您的预期。
P.S 我无法测试此代码,因此它可能不是 100%,但这是一般要点。