Reputation: 3365
I have a file called constants
with a series of string values that get imported into the file where init()
is defined. I want to setup my test so that the string values are different between each run. Right now I can only seem to have them be the same for all test runs.
jest.mock('../src/constants', () => ({
build: 'dist',
action: {
pusher: {
name: 'montezuma',
email: 'best@cat'
},
gitHubToken: 'exists'
}
}));
describe('git', () => {
describe('init', () => {
it('should execute three commands', async () => {
await init();
expect(execute).toBeCalledTimes(3);
});
it('should fail if the deployment folder begins with /', async () => {
// I want the values of constants to be different in here.
});
});
});
How can I set it up so action
and build
have different values in each test run? I've tried moving the jest.mock
call into each it
statement but that doesn't seem to work. Is there a better pattern for this?
Upvotes: 0
Views: 352
Reputation: 102267
You can use jest.spyOn(object, methodName, accessType?) to mock the return value for each unit test case.
E.g.
contants.ts
:
export function get() {
return {
build: 'dist',
action: {
pusher: {
name: 'montezuma',
email: 'best@cat'
},
gitHubToken: 'exists'
}
};
}
index.ts
:
import { get } from './constants';
export async function init() {
return get();
}
index.spec.ts
:
import { init } from './';
import * as constants from './constants';
describe('git', () => {
describe('init', () => {
afterEach(() => {
jest.restoreAllMocks();
});
it('t-1', async () => {
const mConstants = {
build: '/',
action: {
pusher: {
name: 'asd',
email: 'as@cat'
},
gitHubToken: 'ccsa'
}
};
const spy = jest.spyOn(constants, 'get').mockReturnValueOnce(mConstants);
const actualValue = await init();
expect(actualValue).toEqual(mConstants);
expect(spy).toBeCalledTimes(1);
});
it('t-2', async () => {
const mConstants = {
build: 'build',
action: {
pusher: {
name: 'zzz',
email: 'www@cat'
},
gitHubToken: 'xxx'
}
};
const spy = jest.spyOn(constants, 'get').mockReturnValueOnce(mConstants);
const actualValue = await init();
expect(actualValue).toEqual(mConstants);
expect(spy).toBeCalledTimes(1);
});
});
});
Unit test result:
PASS src/stackoverflow/58758771/index.spec.ts (7.685s)
git
init
✓ t-1 (5ms)
✓ t-2 (2ms)
Test Suites: 1 passed, 1 total
Tests: 2 passed, 2 total
Snapshots: 0 total
Time: 8.829s
Update, we can also change the constants object for each unit test case.
Before running the unit test, we should store the original constants. After each test case is finished, we should restore the original constants. I use lodash.cloneDeep
method to make a deep clone for constants.
constants.ts
:
export const constants = {
build: 'dist',
action: {
pusher: {
name: 'montezuma',
email: 'best@cat'
},
gitHubToken: 'exists'
}
};
index.ts
:
import { constants } from './constants';
export async function init() {
return constants;
}
index.spec.ts
:
import { init } from './';
import { constants } from './constants';
import _ from 'lodash';
const originalConstants = _.cloneDeep(constants);
describe('git', () => {
afterEach(() => {
_.assignIn(constants, originalConstants);
});
describe('init', () => {
it('t-1', async () => {
Object.assign(constants, {
build: '/',
action: {
...constants.action,
pusher: { ...constants.action.pusher, name: 'aaa', email: 'aaa@cat' },
gitHubToken: 'bbb'
}
});
const actualValue = await init();
expect(actualValue).toEqual({
build: '/',
action: {
pusher: {
name: 'aaa',
email: 'aaa@cat'
},
gitHubToken: 'bbb'
}
});
});
it('should restore original contants', () => {
expect(constants).toEqual({
build: 'dist',
action: {
pusher: {
name: 'montezuma',
email: 'best@cat'
},
gitHubToken: 'exists'
}
});
});
});
});
Unit test result:
PASS src/stackoverflow/58758771/v2/index.spec.ts (10.734s)
git
init
✓ t-1 (7ms)
✓ should restore original contants (1ms)
Test Suites: 1 passed, 1 total
Tests: 2 passed, 2 total
Snapshots: 0 total
Time: 12.509s
Source code: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/58758771
Upvotes: 1