Reputation: 48909
I'm using Jest with TypeScript (using ts-jest
). This is my test subject which uses dotenv
library:
import * as dotenv from 'dotenv';
export class TestSubject {
public function test() {
console.log(dotenv); // Here I debug if I'm using a mock or not
}
}
I'd like to mock dotenv
library only for a specific test, but I'm stuck.
Here is my test suite:
import { TestSubject } from './test-subject';
import * as dotenv from 'dotenv';
jest.mock('dotenv'); // place it here, otherwise it doesn't work
describe('Suite 1', () => {
it('test 1', () => {
// I want to use the mock here... and it works
const subject = new TestSubject();
subject.test(); // shows that I'm using the mock
});
it('test 2', () => {
// I don't want the mock here
jest.dontMock('dotenv'); // doesn't work
jest.unmock('dotenv'); // doesn't work
const subject = new TestSubject();
subject.test(); // shows that I'm still using the mock!!!
});
});
As you can see, the call jest.mock('dotenv')
should be placed outside describe, otherwise, it doesn't work.
I'm trying to do not use the mock in test 2, but it doesn't work: console.log
shows that I'm using the mock.
Upvotes: 5
Views: 4418
Reputation: 473
An improvement to @slideshowp2's solution.
With jest.domock
you need to call require
afterwards the module(like here), but the result of require
has the any
type and we lose type safety. so you can use typescript's dynamic imports.
Example complete code:
import * as summer from './exampleModule';
describe('mock vs no-mock', () => {
beforeEach(() => {
jest.resetModules();
});
it('NO-MOCKED', async () => {
console.log(summer.sum(1, 1));
expect(summer.sum(1, 1)).toBe(2);
});
it('MOCKED', async () => {
jest.doMock('./exampleModule');
const summer = await import('./exampleModule');
const mockedSummer = mocked(summer, true);
mockedSummer.sum.mockImplementation((a, b) => a + b + 1);
console.log(summer.sum(1, 1));
expect(summer.sum(1, 1)).toBe(3);
});
it('NO-MOCKED', async () => {
console.log(summer.sum(1, 1));
expect(summer.sum(1, 1)).toBe(2);
});
});
Upvotes: 4
Reputation: 102337
Here is the solution:
index.ts
, the file will be tested:
import * as dotenv from 'dotenv';
export class TestSubject {
public test() {
console.log(dotenv);
}
}
Unit test:
describe('TestSubject', () => {
beforeEach(() => {
jest.resetModules();
});
it('should mock dotenv', () => {
jest.doMock('dotenv');
const dotenv = require('dotenv');
const { TestSubject } = require('./');
const subject = new TestSubject();
subject.test();
expect(jest.isMockFunction(dotenv.config)).toBeTruthy();
});
it('should not mock dotenv', () => {
jest.unmock('dotenv');
const dotenv = require('dotenv');
const { TestSubject } = require('./');
const subject = new TestSubject();
subject.test();
expect(jest.isMockFunction(dotenv.config)).toBeFalsy();
});
});
Unit test result:
PASS src/stackoverflow/56446543/index.spec.ts
TestSubject
✓ should mock dotenv (2111ms)
✓ should not mock dotenv (2ms)
console.log src/stackoverflow/56446543/index.ts:5
{ config:
{ [Function: config]
_isMockFunction: true,
getMockImplementation: [Function],
mock: [Getter/Setter],
mockClear: [Function],
mockReset: [Function],
mockRestore: [Function],
mockReturnValueOnce: [Function],
mockResolvedValueOnce: [Function],
mockRejectedValueOnce: [Function],
mockReturnValue: [Function],
mockResolvedValue: [Function],
mockRejectedValue: [Function],
mockImplementationOnce: [Function],
mockImplementation: [Function],
mockReturnThis: [Function],
mockName: [Function],
getMockName: [Function] },
parse:
{ [Function: parse]
_isMockFunction: true,
getMockImplementation: [Function],
mock: [Getter/Setter],
mockClear: [Function],
mockReset: [Function],
mockRestore: [Function],
mockReturnValueOnce: [Function],
mockResolvedValueOnce: [Function],
mockRejectedValueOnce: [Function],
mockReturnValue: [Function],
mockResolvedValue: [Function],
mockRejectedValue: [Function],
mockImplementationOnce: [Function],
mockImplementation: [Function],
mockReturnThis: [Function],
mockName: [Function],
getMockName: [Function] },
default:
{ config:
{ [Function: config]
_isMockFunction: true,
getMockImplementation: [Function],
mock: [Getter/Setter],
mockClear: [Function],
mockReset: [Function],
mockRestore: [Function],
mockReturnValueOnce: [Function],
mockResolvedValueOnce: [Function],
mockRejectedValueOnce: [Function],
mockReturnValue: [Function],
mockResolvedValue: [Function],
mockRejectedValue: [Function],
mockImplementationOnce: [Function],
mockImplementation: [Function],
mockReturnThis: [Function],
mockName: [Function],
getMockName: [Function] },
parse:
{ [Function: parse]
_isMockFunction: true,
getMockImplementation: [Function],
mock: [Getter/Setter],
mockClear: [Function],
mockReset: [Function],
mockRestore: [Function],
mockReturnValueOnce: [Function],
mockResolvedValueOnce: [Function],
mockRejectedValueOnce: [Function],
mockReturnValue: [Function],
mockResolvedValue: [Function],
mockRejectedValue: [Function],
mockImplementationOnce: [Function],
mockImplementation: [Function],
mockReturnThis: [Function],
mockName: [Function],
getMockName: [Function] } } }
console.log src/stackoverflow/56446543/index.ts:5
{ config: [Function: config],
parse: [Function: parse],
default: { config: [Function: config], parse: [Function: parse] } }
Test Suites: 1 passed, 1 total
Tests: 2 passed, 2 total
Snapshots: 0 total
Time: 3.394s, estimated 4s
As you can see, the dotenv
module is mocked for the first test case and is not mocked for the second test case.
You can find the completed demo here: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/56446543
Upvotes: 3