繁体   English   中英

Angular单元测试,模拟使用$ injector注入的服务

[英]Angular unit tests, mocking a service that is injected using $injector

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

被测服务确定应用程序是在线还是离线,然后使用策略模式进行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
                }
            )
    }

}

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM