Reputation: 2447
In the codes below I am trying to test the "someMethodToTest" method, but the "someDependencyMethod" method should be mocked. However, the demonstrated approach is not working as the exception "I MUST NOT BE CALLED!" is being launched every time I run the tests with Jest...
FAIL src/user-files/user-files.service.spec.ts (0.123 s)
● SomeClassToTest › test someMethodToTest
thrown: "I MUST NOT BE CALLED!"
NOTES: I - This is a NestJS application; II - Tests using Jest; III - The code is simplified to facilitate understanding.
I've tried many, many approaches...
QUESTION: What is wrong with the code? Why does the "someDependencyMethod" method keep being called? 😐
Thanks! 🤗
[Ref(s).: How to Mock dependencies with Jest ]
some-mdl-to-test.service.ts
import { Injectable } from '@nestjs/common';
import { SomeDependencyClass } from './some-dependency-mdl';
@Injectable()
export class SomeClassToTest {
async someMethodToTest(someMethodToTestArg: string): Promise<string> {
const someDependencyMethodOutput: string = await new SomeDependencyClass().someDependencyMethod(someMethodToTestArg);
return someDependencyMethodOutput;
}
}
some-dependency-mdl.ts
export class SomeDependencyClass {
async someDependencyMethod(someDependencyMethodArg: string): Promise<string> {
throw 'I MUST NOT BE CALLED!';
// ...
// SOME LOGIC!
// ...
return "SOME_VALUE_A";
}
}
some-mdl-to-test.service.spec.ts
import { Test, TestingModule } from '@nestjs/testing';
import { SomeClassToTest } from './some-mdl-to-test.service';
import { SomeDependencyClass } from './some-dependency-mdl';
describe('SomeClassToTest', () => {
let someClassToTest: SomeClassToTest;
let someDependencyClass: SomeDependencyClass;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [SomeClassToTest, SomeDependencyClass],
}).compile();
someClassToTest = module.get<SomeClassToTest>(SomeClassToTest);
someDependencyClass = module.get<SomeDependencyClass>(SomeDependencyClass);
});
it('should be defined', () => {
expect(someClassToTest).toBeDefined();
});
it('Test someMethodToTest!', async () => {
const someDependencyMethodOutputMock = "SOME_VALUE_A";
const someMethodToTestInputMock = "SOME_VALUE_B";
const someMethodToTestOutput = "SOME_VALUE_A";
const someDependencyMethodPromise: Promise<string> = Promise.resolve(someDependencyMethodOutputMock);
jest.spyOn(someDependencyClass, 'someDependencyMethod').mockImplementation(() => someDependencyMethodPromise);
const someMethodToTestOutputToCheck = await someClassToTest.someMethodToTest(someMethodToTestInputMock);
expect(someMethodToTestOutputToCheck).toEqual(someMethodToTestOutput);
});
});
Upvotes: 0
Views: 3956
Reputation: 995
Well, the problem is how you are injecting your dependencies. In the sense that, with the code you provided, you are not injecting the dependencies.
If your SomeClassToTest
would look like:
@Injectable()
export class SomeClassToTest {
constructor(
@Inject(SomeDependencyClass)
private readonly someDependencyClass: SomeDependencyClass
) {}
async someMethodToTest(someMethodToTestArg: string): Promise<string> {
return await this.someDependencyClass.someDependencyMethod(
someMethodToTestArg
);
}
}
Your tests could look something like:
describe("SomeClassToTest", () => {
let someClassToTest: SomeClassToTest;
const mockReturnValue = "SOME_VALUE_A",
mockDependencyClass: SomeDependencyClass = {
someDependencyMethod: async (): Promise<string> => {
throw new Error("ups");
},
};
beforeEach(() => {
jest.clearAllMocks();
jest
.spyOn(mockDependencyClass, "someDependencyMethod")
.mockImplementation(async () => mockReturnValue);
});
beforeEach(async () => {
const module = await Test.createTestingModule({
providers: [
SomeClassToTest,
{ provide: SomeDependencyClass, useValue: mockDependencyClass },
],
}).compile();
someClassToTest = module.get(SomeClassToTest);
});
it("should be defined", () => {
expect(someClassToTest).toBeDefined();
});
it("Test someMethodToTest!", async () => {
const someMethodToTestOutputToCheck =
await someClassToTest.someMethodToTest("something");
expect(someMethodToTestOutputToCheck).toEqual(mockReturnValue);
});
});
Let me know if something needs more clarifying :)
Going through Nest overview and fundamentals should give you enough to understand the code above
Upvotes: 3