I have a relatively simple Typescript class and method that I want to test using Jest. The goal is to mock out the dependencies of this method:
import {DynamoWorkflow} from '..';
import {Injectable} from '@nestjs/common';
@Injectable()
export class PipelineService {
getCoverageByServiceName(serviceName: string): Promise<QueryResult<PipelineEvent>> {
return new DynamoWorkflow().queryPipelineEvents(serviceName);
}
}
In my testing process, I need to ensure that the argument passed to the .queryPipelineEvents()
method matches my expectations. However, achieving this has proven to be challenging.
Below is my current test setup:
// setting up mock data...
const mockPipelineEvent: PipelineEvent = new PipelineEvent();
mockPipelineEvent.aut = "fake data";
const mockPipelineEvents: PipelineEvent[] = [mockPipelineEvent];
const mockQueryResult = {results: mockPipelineEvents, total: 1};
// creating a mocked 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 should return the same data as obtained from the database", () => {
const methodArg = "foo-service";
const serviceUnderTest = new PipelineService();
const actualResult = serviceUnderTest.getCoverageByServiceName(methodArg);
// Test #1: checking if the dependency was called
expect(mockDynamo).toHaveBeenCalledTimes(1); //PASSES
// Test #2: verifying if the correct argument was passed to the dependency method
const mockedDynamoInstance = mockDynamo.mock.instances[0];
const mockedDynamoMethod = mockedDynamoInstance.queryPipelineEvents;
expect(mockedDynamoMethod.mock.calls[0][0]).toBe(methodArg);
// Test #3: confirming that the result matches our expectation
expect(actualResult).resolves.toEqual(mockQueryResult); //PASSES
});
})
The code above encounters a compilation issue with the error message:
Property 'mock' does not exist on type '(serviceName: string) => Promise<QueryResult<PipelineEvent>>'.ts(2339)
.
The problematic segment of code was referenced from Jest's official documentation.
I've attempted alternatives like
expect(mockDynamo.queryPipelineEvents).toBeCalledWith(methodArg);
, but faced another compilation error: Property 'queryPipelineEvents' does not exist on type 'MockedObjectDeep<typeof DynamoWorkflow>'.ts(2339)
Another approach involved using
expect(mockDynamo.mock.instances[0].queryPipelineEvents).toBeCalledWith(methodArg);
, which compiled and executed successfully. However, it failed during execution with the following message:
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);
If anyone can guide me on how to properly validate the arguments of a mocked method, your assistance would be greatly appreciated.