Angular 5: Testing a service using window

大憨熊 提交于 2019-12-11 16:10:35

问题


I have a service that has a method that checks the available browser quota storage and returns an Observable:

import { Injectable } from "@angular/core";
import { Observable } from "rxjs/Observable";

@Injectable()
export class StorageService {
    hasAvailableStorage(): Observable<boolean> {
        const nav: any = navigator;

        return Observable.create(observer => {
            nav.webkitTemporaryStorage.queryUsageAndQuota(
                (usedBytes, grantedBytes) => {
                    observer.next(usedBytes <= grantedBytes * 0.8);
                }
            );
        });
    }
}

I want to unit test this service, but I don't know how to get access to the window in the test or to mock the window/webkitTemporaryStorage.

I tried the following, but then it gives an error that the window.webkitTemporaryStorage is read only and cannot be assigned to:

import { Injectable } from "@angular/core";

import { StorageService } from "./storage.service";

@Injectable()
class MockWebkitTemporaryStorage {
    queryUsageAndQuota(cb) {
        return cb(10, 15);
    }
}

describe("storage.service", () => {
    let service: StorageService;

    const nav: any = window.navigator;
    nav.webkitTemporaryStorage = MockWebkitTemporaryStorage;

    beforeAll(() => {
        service = new StorageService();
    });

    it("should return the result of hasAvailableStorage()", () => {
        const result = service.hasAvailableStorage();
        expect(result).toBeDefined();
    });
});

I am expecting that I have to use some kind of spy on the window navigator/queryUsageAndQuota eventually, but I cannot see how I should set up or complete the test in order to do this. It would be great if someone could help me and provide some example in a detail! :)

EDIT changed test (after comments):

describe("storage.service", () => {
    let service: StorageService;

    beforeAll(() => service = new StorageService());

    it("should return the result of hasAvailableStorage()", () => {
        const spy = spyOn(navigator["webkitTemporaryStorage"], "queryUsageAndQuota").and.callFake(MockWebkitTemporaryStorage);
        const result = service.hasAvailableStorage();
        expect(spy).toHaveBeenCalled();
        expect(result).toBeDefined();
    });
});

After this, the test fails with the error: 'Expected spy queryUsageAndQuota to have been called.'


回答1:


After your answer to my comment, here is my answer : you are not testing it right.

Since those methods are native methods (that I assume you don't override), you should not test if they work. They're made to work. What you should test is if they're called.

Your test should look like this :

describe("storage.service", () => {
    let service: StorageService;

    beforeAll(() => service = new StorageService());

    it("should return the result of hasAvailableStorage()", () => {
        const spy = spyOn(navigator["webkitTemporaryStorage"], "queryUsageAndQuota").and.callFake(MockWebkitTemporaryStorage);
        service.hasAvailableStorage().subscribe(() => {
            expect(spy).toHaveBeenCalled();
        });
    });
});

Now you are testing if the navigator calls the right function, you mock this function, return something, and you expect the function to have been called.

This should do the trick.



来源:https://stackoverflow.com/questions/48165201/angular-5-testing-a-service-using-window

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!