如何窥探指令链接中的服务功能?

时间:2015-06-08 11:26:00

标签: testing service angularjs-directive jasmine angularjs-service

我有一个使用像这样的服务函数的指令:

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

在上面的指令中,我注入了我想要使用的服务,这个服务函数在范围函数“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();

}));

现在我有一个测试运行并传递wherby我可以窥探隔离范围函数“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();
}));

如何成功测试是否已在此处调用服务功能?

1 个答案:

答案 0 :(得分:1)

在写这个例子时,我已经解决了我的问题。在我的实际代码中,在测试内部&#34; serviceFunction运行&#34;我还包括spyOn(isoScope,"getRequiredData)"

这会阻止函数的内部功能

getRequiredData()

这意味着getRequiredData中的服务函数永远不能运行。

要解决此问题,我需要编辑外部函数的间谍

从:

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