簡體   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