unit-testing - Nestjs中的单元测试ClientProxy
问题描述
在 Nestjs 中,我尝试模拟 ClientProxy,但我收到一个输入错误,告诉我需要定义 ClientProxy 类的所有属性。当然,我不想模拟这个类的每个属性。关于如何解决这个问题的任何想法?
这是一段简化的代码:
服务.ts
@Injectable()
export class SimulationsService {
constructor() {}
@Client({
transport: Transport.NATS,
options: {
url: env.nats,
user: env.usernats,
pass: env.passnats,
},
})
simulationClient: ClientProxy;
method1(){
this.simulationClient.send('simulatePattern', simulation)
.pipe(
map(sim=>{
//SOME CODE
return sim;
})
});
}
服务规范.ts
describe('method1', () => {
it('should return a processed Simulation', async () => {
jest.spyOn(
service,
'simulationClient',
'get',
).mockImplementation(()=>{
return {send() {
return of(simulationMock as Simulation);
}}
});
});
expect(await service.update('test', unfedSimulationMock)).toEqual(simulationMock);
});
});
错误输出:
类型 '{ send(): Observable; }' 缺少“ClientProxy”类型的以下属性:connect、close、routingMap、emit 等 7 个。
解决方案
这是一个解决方案:
export interface ClientProxy {
send(pattern: string, simulation: any): any;
connect(): any;
close(): any;
routingMap(): any;
}
我简化了以下代码service.ts
:
// tslint:disable-next-line: interface-name
export interface ClientProxy {
send(pattern: string, simulation: any): any;
connect(): any;
close(): any;
routingMap(): any;
}
export class SimulationsService {
constructor(private simulationClient: ClientProxy) {}
public method1() {
const simulation = {};
this.simulationClient.send('simulatePattern', simulation);
}
}
单元测试,部分模拟ClientProxy
,这意味着我们可以模拟特定方法而不会出现类型错误。
import { SimulationsService, ClientProxy } from './service';
import { mock } from '../../__utils';
const simulationClientMock = mock<ClientProxy>('send');
// Argument of type '{ send: Mock<any, any>; }' is not assignable to parameter of type 'ClientProxy'.
// Type '{ send: Mock<any, any>; }' is missing the following properties from type 'ClientProxy': connect, close, routingMap
// const simulationClientMock = {
// send: jest.fn()
// };
const service = new SimulationsService(simulationClientMock);
describe('SimulationsService', () => {
describe('#method1', () => {
it('t1', () => {
simulationClientMock.send.mockReturnValueOnce('mocked data');
service.method1();
expect(simulationClientMock.send).toBeCalledWith('simulatePattern', {});
});
});
});
__util.ts
:
type GenericFunction = (...args: any[]) => any;
type PickByTypeKeyFilter<T, C> = {
[K in keyof T]: T[K] extends C ? K : never;
};
type KeysByType<T, C> = PickByTypeKeyFilter<T, C>[keyof T];
type ValuesByType<T, C> = {
[K in keyof T]: T[K] extends C ? T[K] : never;
};
type PickByType<T, C> = Pick<ValuesByType<T, C>, KeysByType<T, C>>;
type MethodsOf<T> = KeysByType<Required<T>, GenericFunction>;
type InterfaceOf<T> = PickByType<T, GenericFunction>;
type PartiallyMockedInterfaceOf<T> = {
[K in MethodsOf<T>]?: jest.Mock<InterfaceOf<T>[K]>;
};
export function mock<T>(...mockedMethods: Array<MethodsOf<T>>): jest.Mocked<T> {
const partiallyMocked: PartiallyMockedInterfaceOf<T> = {};
mockedMethods.forEach(mockedMethod => (partiallyMocked[mockedMethod] = jest.fn()));
return partiallyMocked as jest.Mocked<T>;
}
覆盖率 100% 的单元测试结果:
PASS src/stackoverflow/57960039/service.spec.ts
SimulationsService
#method1
✓ t1 (4ms)
----------------------------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
----------------------------|----------|----------|----------|----------|-------------------|
All files | 100 | 100 | 100 | 100 | |
src | 100 | 100 | 100 | 100 | |
__utils.ts | 100 | 100 | 100 | 100 | |
src/stackoverflow/57960039 | 100 | 100 | 100 | 100 | |
service.ts | 100 | 100 | 100 | 100 | |
----------------------------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 3.234s, estimated 6s
这是完成的演示:https ://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/57960039
推荐阅读
- clojure - r/foldcat 的返回值根据数据大小而变化
- c - 如何查找大小大于元素的数组元素的数量
- algorithm - 将“弹出列表”转换为“索引列表”的高效算法
- pentaho - Pentaho Server 8.2 无法解析转换中的文件路径
- wpf - 当给出同一类的对象列表和属性字符串列表时,如何实现 DataGrid?
- sql - 使用 IN 子查询时的基于函数的索引
- mysql - PHPMyAdmin 显示错误“未捕获的类型错误”
- ios - 如果 JSON 数据的值满足某些参数,如何重命名它们?
- amazon-web-services - EC2 没有剩余空间,无法找出正在使用的空间
- android - 如何在 Android 的倒数计时器应用程序中包含休息时间?