Angular 5:使用 window 测试服务

Angular 5: Testing a service using window

我有一个服务,它有一个方法可以检查可用的浏览器配额存储和 returns 一个 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);
                }
            );
        });
    }
}

我想对该服务进行单元测试,但我不知道如何在测试中访问 window 或模拟 window/webkitTemporaryStorage。

我尝试了以下操作,但随后出现错误,指出 window.webkitTemporaryStorage 是只读的,无法分配给:

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

我预计我最终必须在 window navigator/queryUsageAndQuota 上使用某种间谍程序,但我不知道我应该如何设置或完成测试才能执行此操作。如果有人可以帮助我并详细提供一些示例,那就太好了! :)

编辑 更改测试(评论后):

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

在此之后,测试失败并出现错误:'Expected spy queryUsageAndQuota to have been called.'

在您回答我的评论后,这是我的回答:您没有正确测试

由于这些方法是本机方法(我假设您不会重写),因此您不应测试它们是否有效。他们被用来工作。您应该测试的是它们是否被调用

您的测试应如下所示:

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

现在你正在测试导航器是否调用了正确的函数,你模拟了这个函数,return 一些东西,你期望函数被调用。

这应该可以解决问题。