我有一个使用如下服务函数的指令:
angular.module('testModule',
['serviceBeingUsed'])
.directive('testDirective', function(serviceBeingUsed) {
return {
restrict: 'AE',
templateUrl: 'testTemplate.tpl.html',
scope: {
boundVar1: "="
},
link: function(scope) {
scope.getRequiredData = function(data){
//gether data using service
serviceBeingUsed.fetchRequiredData(data).then(
function(result){
scope.requiredData = result;
}
);
};
}
};
});
在上面的指令中,我注入了我想要使用的服务,这个服务函数在该指令的"link"内部的作用域函数"getRequiredData()"中使用。
我有我的测试套件设置如下:
describe('test suite', function () {
var scope,
$rootScope,
$compile,
$q,
element,
isoScope,
serviceBeingUsed;
beforeEach(module('testModule'));
beforeEach( inject( function(_$rootScope_,
_$q_,
_$compile_,
_serviceBeingUsed_) {
$rootScope = _$rootScope_;
$compile = _$compile_;
serviceBeingUsed = _serviceBeingUsed_;
$q = _$q_;
//This is where we create the directive and it's options.
element = angular.element('<test-directive bound-var1="blabla"></test-directive>');
//We create a new scope from the rootScope.
scope = $rootScope.$new();
//Now we compile the HTML with the rootscope
$compile(element)(scope);
//digest the changes
scope.$digest();
//We retrieve the isolated scope scope of the directive
isoScope = element.isolateScope();
}));
现在我有一个运行并通过的测试,我可以在孤立的作用域函数"getRequiredData()"中窥探,这个测试看起来像这样:
it('getRequiredData runs', inject(function () {
spyOn(isoScope,"getRequiredData");
isoScope.getRequiredData();
expect(isoScope.getRequiredData).toHaveBeenCalled();
}));
这证明了链接函数可以被测试,但是当试图测试服务函数是否被调用时,测试失败了,我不知道为什么,服务的测试看起来像这样:
it('serviceFunction runs', inject(function () {
spyOn(serviceBeingUsed, "serviceFunction").and.callFake(function() {
var deferred = $q.defer();
var data = "returnedDataDummy";
deferred.resolve(data);
return deferred.promise;
});
isoScope.getRequiredData();
expect(serviceBeingUsed.serviceFunction).toHaveBeenCalled();
}));
如果在这里调用了业务功能,如何成功测试?
通过写这个例子,我已经解决了我的问题。在我的实际代码中,在测试"serviceFunction runs"中,我还包含了一个spyOn(isoScope,"getRequiredData)"
这会阻塞函数
的内部功能。getRequiredData()
这意味着getRequiredData中的service函数永远不能运行。
为了解决这个问题,我需要编辑外部函数的间谍
来自:spyOn(isoScope,"getRequiredData");
:
spyOn(isoScope,"getRequiredData").and.callThrough();
这个简单的更改意味着被监视的函数也将运行其内部代码,而不仅仅是注册它已被调用。
然而,我学到的一个重要的教训是不要在每次考试中做太多的事情,并且尽可能地将考试分开。
所以为了澄清,我的原始测试失败了看起来像这样:
it('getRequiredData runs', inject(function () {
spyOn(serviceBeingUsed, "serviceFunction").and.callFake(function() {
var deferred = $q.defer();
var data = "returnedDataDummy";
deferred.resolve(data);
return deferred.promise;
});
spyOn(isoScope,"getRequiredData");
isoScope.getRequiredData();
expect(serviceBeingUsed.fetchRequiredData).toHaveBeenCalled();
expect(isoScope.getRequiredData).toHaveBeenCalled();
}));
it('getRequiredData runs', inject(function () {
spyOn(serviceBeingUsed, "serviceFunction").and.callFake(function() {
var deferred = $q.defer();
var data = "returnedDataDummy";
deferred.resolve(data);
return deferred.promise;
});
spyOn(isoScope,"getRequiredData").and.callThrough();
isoScope.getRequiredData();
expect(serviceBeingUsed.fetchRequiredData).toHaveBeenCalled();
expect(isoScope.getRequiredData).toHaveBeenCalled();
}));