javascript - Angular 单元测试,模拟使用 $injector 注入(inject)的服务

标签 javascript angularjs unit-testing jasmine

我正在尝试对 Angular 服务进行单元测试,该服务使用 $injector 注入(inject)另一个服务,而不是将服务依赖项作为参数传递。注入(inject)的服务是动态的 - 它可能是许多不同服务之一 - 因此它不能作为函数参数传递。

被测服务确定应用程序是在线还是离线,然后使用策略模式进行 HTTP 调用(我们在线,因此策略是“远程”)或使用本地存储来获取所需的数据(我们处于离线状态,因此策略是“本地”)。它在应用程序中的许多场景中使用,因此服务和随后调用的服务方法是动态的。更容易显示简化的相关代码:

class NetworkStrategyService {
    constructor (private Offline, private $injector) {}

    fulfill (config) {
        this.Offline.check()
            .then(
                () => {
                    // we're online
                    const service = $injector.get(config.remote.service);
                    service[config.remote.method](config.remote.data)
                        .then(() => {
                            // Do something with the data
                        })
                },
                () => {
                    // Grab it from local storage
                }
            )
    }

}

我的问题是,因为我无法在单元测试中以正常方式注入(inject)服务,所以我不知道如何测试这段代码。我已经模拟了配置,现在我想测试在线和离线时是否调用了正确的服务方法,例如:

it (`calls the remote service, with the remote method, if we're online`, () => {
    const remoteMethod = spyOn(config.remote.service, config.remote.method);
    // Set up, to get a successful Offline.check() outcome
    expect(remoteMethod).toHaveBeenCalledWith(config.remote.data);
});

如何确保模拟的服务一个服务,并将其传递到我正在测试的服务中?

最佳答案

好吧,我似乎已经解决了:

let deferred;
let config = {
    remote: {
        service: 'RemoteService',
        method: 'remoteAction',
        data: {alpha:1}
    },
    local: ...
};

beforeEach(() => {
    angular.mock.module(($provide) => {
        $provide.service(config.remote.service, () => {
            return {
                [config.remote.method]: () => {}
            };
        });
    });
});

beforeEach(() => {
    inject((_$q_, _$rootScope_, _$injector_) => {
        $q = _$q_;
        $scope = _$rootScope_.$new();
        $injector = _$injector_
    });
    deferred = $q.defer();
});

beforeEach(() => serviceUnderTest = new NetworkStrategyService(Offline, $injector));

it (`calls the remote service, with the remote method, if we're online`, () => {
    let dynamicService;
    inject((_RemoteService_) => {
        dynamicService = _RemoteService_;
    });
    serviceUnderTest.strategy = 'remote';
    const dynamicMethod = spyOn(dynamicService, config.remote.method).and.returnValue(deferred.promise);
    serviceUnderTest.makeCall(config);
    deferred.resolve();
    $scope.$apply();
    expect(dynamicMethod).toHaveBeenCalledWith(config.remote.data);
});

关于javascript - Angular 单元测试,模拟使用 $injector 注入(inject)的服务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40180818/

相关文章:

javascript - 使用ng-flow取文件时如何将文件发送到node.js和后端

angularjs - 重新加载数据后如何刷新 UI-Grid 布局

javascript - 在 AngularJS 中为自定义指令加上前缀 'ng' 是否明智?

javascript - 监视解构的 require 方法

javascript - 无法纠正错误 "Fail 1 - Table tag should have 3 rows and check with the requirements for CSS for table and tr"

javascript - ctrl + click of href=# 出现问题

javascript - Jquery - 从选择框进行数组操作

unit-testing - 单元测试 C++ SetUp() 和 TearDown()

angular - 使用 Jasmine 测试 Angular queryParams

javascript - Typescript/Angular 中的动态谷歌可视化