angular - 使用导入的第三方依赖项对 Angular 服务方法进行单元测试

标签 angular unit-testing jestjs angular-services

我有一个 Angular 服务,它导入第三方依赖项。我调用依赖项来为我提供浏览器指纹,然后将其存储在服务中。

我不确定如何在测试中模拟此依赖项,以便我可以断言它已被调用并模拟返回值。

这是服务:

import { Inject, Injectable } from '@angular/core';
import * as Fingerprint2 from 'fingerprintjs2';

@Injectable()
export class ClientInfoService {
    public fingerprint: string | null = null;

    constructor() {
    }

    createFingerprint(): any {
        return new Fingerprint2();
    }

    setFingerprint(): void {
        let fprint = this.createFingerprint();
        setTimeout(() => fprint.get(hash => this.fingerprint = hash), 500);
    }

    getFingerprint(): string | null {
        return this.fingerprint;
    }

}

这是当前的测试代码:

import { TestBed } from '@angular/core/testing';
import { ClientInfoService } from './client-info.service';

describe('Client Info Service', () => {
    const hash = 'a6e5b498951af7c3033d0c7580ec5fc6';
    let service: ClientInfoService;

    beforeEach(() => {
        TestBed.configureTestingModule({
            providers: [ClientInfoService],
        });
        service = TestBed.get(ClientInfoService);
    });

    test('should be defined', () => {
        expect(service).toBeDefined();
    });


    describe('get the fingerprint', () => {

        test('it should be null', () => {
            let fprint = service.getFingerprint();
            expect(fprint).toBeNull();
        });

        test('it should be the hash value', () => {
            service.fingerprint = hash;
            let fprint = service.getFingerprint();
            expect(fprint).toEqual(hash);
        });

    test('it should get the hash value after setting', () => {
        jest.useFakeTimers();
        service.createFingerprint = jest.fn().mockReturnValue(() => {
            return {
                get: function (cb) {
                    return cb(hash);
                }
            };
        });
        spyOn(service, 'createFingerprint');
        service.setFingerprint();
        jest.runAllTimers();
        expect(service.createFingerprint).toHaveBeenCalled();
        expect(service.fingerprint).toEqual(hash);
    });

    });

});

最佳答案

我不会将第三方直接导入到服务中,因为很难对它们进行单元测试(特别是如果他们做了一些棘手的事情,例如 http 调用或 DOM 操作等......)

创建像第三方工厂一样工作的 Angular 服务可能是个好主意:

import * as Fingerprint2 from 'fingerprintjs2';

@Injectable()
export class FingerprintFactory {
    create(): any {
        return new Fingerprint2();
    }
}

之后,您可以在 ClientInfoService 中注入(inject) FingerprintFactory 并使用其 create 方法创建 Fingerprint2 实例。

此外,在 ClientInfoService 中模拟 FingerprintFactory 也非常容易

关于angular - 使用导入的第三方依赖项对 Angular 服务方法进行单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52836002/

相关文章:

node.js - 无法测试 mongo 聚合 MongoError : Unrecognized pipeline stage name: '$set'

unit-testing - 模拟存储库的插入方法

Angular 2 在 Onit 上获取服务值(value)

带复选框的 Angular Material 垫树全选

Angular - 根据所选项目搜索数据

c# - 如何在 WinForms 应用程序中测试 Web 浏览器控件的 Web UI?

c++ - 如何将单元测试与 assert() 相结合

javascript - 开 Jest : window. location.assign 模拟函数未调用..它与 Promise catch() 有关吗?

javascript - 如何向 Jest Expect 添加自定义消息?

angular - CdkVirtualScrollViewport 已附加(错误)