Hol*_*olf 39 unit-testing dependency-injection jasmine angularjs
我正在嘲笑AngularJS单元测试的服务.我正在使用该$provide服务用被模拟的服务替换"真正的"服务(这是一个可用的plunker脚本):
describe('My Controller', function () {
var $scope;
var $provide;
beforeEach(angular.mock.module('myApp'));
beforeEach(angular.mock.module(function (_$provide_) {
$provide = _$provide_;
}));
beforeEach(angular.mock.inject(function($rootScope, $controller, $q){
var mockMyService = {
getAll : function() {
var deferred = $q.defer();
deferred.resolve([
{ itemText: "Foo" },
{ itemText: "Bar" }
]);
return deferred.promise;
}
};
$provide.value('myService', mockMyService);
$scope = $rootScope.$new();
$controller('MyCtrl', { $scope: $scope });
$rootScope.$apply();
}));
it('Has two items defined', function () {
expect($scope.items.length).toEqual(2);
});
});
Run Code Online (Sandbox Code Playgroud)
这很好用.但是,我不喜欢这样一个事实,即我只使用一个angular.mock.module函数来提供对$provide服务的引用,然后在angular.mock.inject下面的函数中使用该服务.但是,如果我直接将其$provide作为参数添加到angular.mock.inject函数中,则会出现"未知提供程序"错误.
在我看来,我可以将所有模拟代码放在angular.mock.module函数中.但是我在$q引用时遇到了类似的问题,因为我的模拟服务必须返回一个promise.
换句话说,如果我$q向angular.mock.module函数添加一个参数,那么我也会得到一个"未知提供者"错误.
有没有办法简化这个?显然我的工作有点但不一定感觉不对.我觉得我不了解为什么某些提供者可以在inject功能中使用,而其他提供者在module功能中可用.
Mic*_*ord 55
您不能$provide在inject函数中使用,因为前者注册后者使用的提供程序.看一看:
describe('...', function() {
beforeEach(function() {
module(function($provide) {
$provide.constant('someValue', 'foobar');
});
inject(function(someValue) {
var value = someValue; // will be 'foobar';
});
});
});
Run Code Online (Sandbox Code Playgroud)
你可以用这种方式编写测试:
describe('...', function() {
var serviceMock;
beforeEach(function() {
serviceMock = {
someMethod: function() { ... }
};
module(function($provide) {
$provide.value('service', serviceMock);
});
inject(function(service) {
...
});
});
});
Run Code Online (Sandbox Code Playgroud)
事实上,在使用以下方法注入之前,您甚至不需要实现模拟服务$provide:
beforeEach(function() {
serviceMock = {};
module(function($provide) {
$provide.value('service', serviceMock);
});
inject(function(service) {
...
});
});
it('tests something', function() {
// Arrange
serviceMock.someMethod = function() { ... }
// Act
// does something
// Assert
expect(...).toBe(...);
});
Run Code Online (Sandbox Code Playgroud)
这是一个Plunker脚本,主要说明了上述内容.
Cla*_*diu 11
当我必须包装一个使用过$q并且看起来很干净的服务时,这对我有用:
var _ServiceToTest_;
beforeEach(function () {
module('module.being.tested');
module(function ($provide) {
$provide.factory('ServiceToMock', function ($q, $rootScope) {
var service = ...;
// use $q et al to heart's content
return service;
});
});
inject(function (_ServiceToTest_) {
ServiceToTest = _ServiceToTest_;
});
});
it('...', function () { /* code using ServiceToTest */ });
Run Code Online (Sandbox Code Playgroud)
诀窍是使用$provide.factory而不是$provide.value.