【问题标题】:How to spyOn a service function within the link of a directive?如何在指令的链接中窥探服务功能?
【发布时间】:2015-08-22 20:20:25
【问题描述】:

我有一个使用如下服务函数的指令:

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

}));

现在我有一个运行并通过的测试,我可以在隔离范围函数“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();
}));

如果这里调用了服务函数,如何才能成功测试?

【问题讨论】:

  • 能否请您发布您遇到的错误?对我来说,这条线有点令人困惑angular.module('testModule', ['serviceBeingUsed']) - 你的服务也是一个模块吗?检查这个plunker
  • 服务也是一个模块,被注入到“angular.module('testModule', ['serviceBeingUsed'])”行中

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


【解决方案1】:

在编写这个示例时,我已经解决了我的问题。在我的实际代码中,在测试“serviceFunction runs”中,我还包含了一个spyOn(isoScope,"getRequiredData)"

这具有阻塞函数内部功能的效果

getRequiredData()

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

为了解决这个问题,我需要为外部函数编辑 spy

来自:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-10-08
    • 2010-10-28
    • 1970-01-01
    • 2020-02-24
    • 2016-12-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多