typescript - 无法检查传递给 Jest 模拟对象的参数
问题描述
我有一个相当直接的 Typescript 类和方法。我想用 Jest 来测试这个方法来模拟这个方法的依赖:
import {DynamoWorkflow} from '..';
import {Injectable} from '@nestjs/common';
@Injectable()
export class PipelineService {
getCoverageByServiceName(serviceName: string): Promise<QueryResult<PipelineEvent>> {
return new DynamoWorkflow().queryPipelineEvents(serviceName);
}
}
在我的测试中,我想确认传递给该方法的参数.queryPipelineEvents()
是我所期望的。我发现这很难完成。
这是我目前的测试:
//setup mock data...
const mockPipelineEvent: PipelineEvent = new PipelineEvent();
mockPipelineEvent.aut = "fake data";
const mockPipelineEvents: PipelineEvent[] = [mockPipelineEvent];
const mockQueryResult = {results: mockPipelineEvents, total: 1};
//setup mock dependency...
jest.mock('../../../../workflows/dynamoworkflow', () => {
return {
DynamoWorkflow: jest.fn().mockImplementation(() => {
return {
queryPipelineEvents: () => Promise.resolve(mockQueryResult),
};
})
};
});
describe("PipelineService", () => {
const mockDynamo = mocked(DynamoWorkflow, true);
beforeEach(() => {
mockDynamo.mockClear();
})
it("getCoverageByServiceName returns same data as db supplies", () => {
const methodArg = "foo-service";
const serviceUnderTest = new PipelineService();
const actualResult = serviceUnderTest.getCoverageByServiceName(methodArg);
// Test #1: confirm the dependency was called
expect(mockDynamo).toHaveBeenCalledTimes(1); //PASSES
// Test #2: confirm the dependency method was called with the correct argument
const mockedDynamoInstance = mockDynamo.mock.instances[0];
const mockedDynamoMethod = mockedDynamoInstance.queryPipelineEvents;
expect(mockedDynamoMethod.mock.calls[0][0]).toHaveBeenCalledWith(methodArg); //ERROR HERE on .mock
// Test #3: confirm the result is what we expect
expect(actualResult).resolves.toEqual(mockQueryResult); //PASSES
});
})
此代码不会编译。消息是Property 'mock' does not exist on type '(serviceName: string) => Promise<QueryResult<PipelineEvent>>'.ts(2339)
。
我已经尝试过expect(mockDynamo.queryPipelineEvents).toBeCalledWith(methodArg);
,但这也不会编译,错误说:Property 'queryPipelineEvents' does not exist on type 'MockedObjectDeep<typeof DynamoWorkflow>'.ts(2339)
我也试过了expect(mockDynamo.mock.instances[0].queryPipelineEvents).toBeCalledWith(methodArg);
。它编译并运行良好,但失败并显示以下消息:
expect(received).toBeCalledWith(...expected)
Matcher error: received value must be a mock or spy function
Received has value: undefined
44 | // expect(mockedDynamoMethod.mock.calls[0][0]).toHaveBeenCalledWith(methodArg);
45 | // expect(mockDynamo.queryPipelineEvents).toBeCalledWith(methodArg);
> 46 | expect(mockDynamo.mock.instances[0].queryPipelineEvents).toBeCalledWith(methodArg);
| ^
47 |
48 | // Test #3: confirm the result is what we expect
49 | expect(actualResult).resolves.toEqual(mockQueryResult);
有人可以帮助我了解如何确认模拟方法的参数符合预期吗?
解决方案
一个同事正在做不同的测试,并偶然发现了这个问题的答案。关键是将模拟方法分配给被模拟的对象和方法。去掉原始代码中的所有模拟,并用以下代码替换它:
jest.mock('../../../../workflows/dynamoworkflow');
const mockMethod = jest.fn();
mockMethod.mockReturnValue(Promise.resolve(mockQueryResult));
DynamoWorkflow.prototype.queryPipelineEvents = mockMethod; //<- key here!
这是完整的工作测试:
describe("PipelineService", () => {
it("getCoverageByServiceName returns same data as db supplies", () => {
//setup mock data...
const mockPipelineEvent: PipelineEvent = new PipelineEvent();
mockPipelineEvent.aut = "fake data";
const mockPipelineEvents: PipelineEvent[] = [mockPipelineEvent];
const mockQueryResult = {results: mockPipelineEvents, total: 1};
//setup mock...
jest.mock('../../../../workflows/dynamoworkflow');
const mockMethod = jest.fn();
mockMethod.mockReturnValue(Promise.resolve(mockQueryResult));
DynamoWorkflow.prototype.queryPipelineEvents = mockMethod;
//exercise the method we're testing...
const methodArg = "foo-service";
const serviceUnderTest = new PipelineService();
const actualResult = serviceUnderTest.getCoverageByServiceName(methodArg);
// and test...
expect(mockMethod).toHaveBeenCalledWith(methodArg);
expect(actualResult).resolves.toEqual(mockQueryResult);
});
})
推荐阅读
- c++ - C++ 中实际需要尾随返回类型的地方?
- node.js - Docker 上的 Adonis ace 迁移 - SyntaxError: Unexpected identifier
- flutter - Flutter:如何从 TextFields 的 ListView.builder 中保存用户的输入
- c++ - 0的2D数组破坏无关循环的逻辑 - C++
- sql - 基于同一列更新
- java - 改造响应在 Android Studio 中返回 null
- javascript - 需要降价文件时,Webpack raw-loader 出错
- c# - 为什么我的 api 控制器中出现此 LINQ 错误?
- apollo - 在 Apollo 中处理未经身份验证的响应
- php - 将付款意图存储在 Stripe php 上后,如何检索其净值