Angular 具有导入的第三方依赖项的服务方法的单元测试
Unit testing for Angular service method with imported third party dependancy
我有一个导入第三方依赖项的 Angular 服务。我调用依赖项给我浏览器指纹,然后将其存储在服务中。
我不确定如何在测试中模拟此依赖关系,因此我可以断言它已被调用并模拟一个 return 值。
这是服务:
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);
});
});
});
我设法通过以下规范实现了这一点。我使用间谍和返回值来模拟指纹创建。
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();
});
test('it should set the fingerprint', () => {
jest.useFakeTimers()
let cb = (h) => {return h;};
spyOn(service, 'createFingerprint').and.returnValue({
get: (cb) => {
return cb(hash);
},
});
service.setFingerprint();
jest.runAllTimers();
expect(service.createFingerprint).toHaveBeenCalled();
expect(service.fingerprint).toEqual(hash);
});
test('it should get the fingerprint', () => {
let fprint = service.getFingerprint();
expect(fprint).toEqual(service.fingerprint);
});
});
我不会将第 3 方直接导入服务,因为很难对它们进行单元测试(特别是如果它们做一些棘手的事情,如 http 调用或 DOM 操作等...)
为第 3 方创建 Angular 像工厂一样工作的服务可能是个好主意:
import * as Fingerprint2 from 'fingerprintjs2';
@Injectable()
export class FingerprintFactory {
create(): any {
return new Fingerprint2();
}
}
之后,您可以在 ClientInfoService
中注入 FingerprintFactory
并使用其 create
方法创建 Fingerprint2
实例。
在你的 ClientInfoService
中模拟 FingerprintFactory
也很容易
我有一个导入第三方依赖项的 Angular 服务。我调用依赖项给我浏览器指纹,然后将其存储在服务中。
我不确定如何在测试中模拟此依赖关系,因此我可以断言它已被调用并模拟一个 return 值。
这是服务:
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);
});
});
});
我设法通过以下规范实现了这一点。我使用间谍和返回值来模拟指纹创建。
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();
});
test('it should set the fingerprint', () => {
jest.useFakeTimers()
let cb = (h) => {return h;};
spyOn(service, 'createFingerprint').and.returnValue({
get: (cb) => {
return cb(hash);
},
});
service.setFingerprint();
jest.runAllTimers();
expect(service.createFingerprint).toHaveBeenCalled();
expect(service.fingerprint).toEqual(hash);
});
test('it should get the fingerprint', () => {
let fprint = service.getFingerprint();
expect(fprint).toEqual(service.fingerprint);
});
});
我不会将第 3 方直接导入服务,因为很难对它们进行单元测试(特别是如果它们做一些棘手的事情,如 http 调用或 DOM 操作等...)
为第 3 方创建 Angular 像工厂一样工作的服务可能是个好主意:
import * as Fingerprint2 from 'fingerprintjs2';
@Injectable()
export class FingerprintFactory {
create(): any {
return new Fingerprint2();
}
}
之后,您可以在 ClientInfoService
中注入 FingerprintFactory
并使用其 create
方法创建 Fingerprint2
实例。
在你的 ClientInfoService
FingerprintFactory
也很容易