I have this tests in my nextjs app:
jest.mock('axios');
describe('Contacts', () => {
afterEach(() => {
axios.get.mockClear();
});
it('first test', async () => {
axios.get.mockImplementation((url: string) => {
if (url.includes('?page=1')) {
return Promise.resolve(ContactsFirstPageResponse);
} else {
return Promise.resolve(ContactsSecondPageResponse);
}
});
// ...
});
it('second test', async () => {
axios.get.mockImplementation(() => Promise.resolve(ContactsEmptyResponse));
// ...
});
});
First test passed, but second received response from ContactsFirstPageResponse
In addition I added auto clearing mocks on jest config:
const nextJest = require('next/jest');
const createJestConfig = nextJest({
dir: './',
});
const { pathsToModuleNameMapper } = require('ts-jest');
const { compilerOptions } = require('./tsconfig');
const customJestConfig = {
setupFilesAfterEnv: ['<rootDir>/jest-setup.js'],
moduleDirectories: ['node_modules', '<rootDir>/'],
testEnvironment: 'jest-environment-jsdom',
moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths),
resetMocks: true,
restoreMocks: true,
};
module.exports = createJestConfig(customJestConfig);
Please for help.
Related
Using pinia, I am not able to test what seems to be a simple scenario.
Store
const useStore = defineStore('store', () => {
const id = ref('id');
const forceId = ref('forceId');
function shouldReturnForceId() {
return false;
}
function getId() {
if (shouldReturnForceId()) {
return forceId.value;
}
return id.value;
}
return {
id,
forceId,
shouldReturnForceId,
getId,
};
});
Helper
const createTestStore = (stubActions: boolean) => {
const pinia = createTestingPinia({
stubActions,
});
setActivePinia(pinia);
const store = useStore();
return store;
};
Test
describe('Pinia Test', () => {
describe('getId', () => {
// DOES NOT WORK - stubAction to false and mocking shouldReturnForceId
it('should return forceId if shouldReturnForceId is true', () => {
const store = createTestStore(false);
store.shouldReturnForceId = jest.fn(() => true);
expect(store.getId()).toEqual('forceId');
});
// DOES NOT WORK - stubAction to true and mocking shouldReturnForceId
it('should return forceId if shouldReturnForceId is true', () => {
const store = createTestStore(true);
store.shouldReturnForceId = jest.fn(() => true);
expect(store.getId()).toEqual('forceId');
});
// WORKS
it('should return id if shouldReturnForceId is false', () => {
const store = createTestStore(false);
expect(store.getId()).toEqual('id');
});
});
});
Question
How is it possible to test a store by only mocking one action among several?
Reading the documentation I get that we can stubActions: true, which will mock all actions, but this is not what I need.
When I tried with basic repository provided typeorm, I think test is completed.
But to do 'unit test' with custom repository of typeorm is not working.
I think mocking custom repository has problem.
What I have to do for mocking custom repostitory?
Next are test file and source file to test.
Thanks.
quests.service.spec.ts
import { Test } from '#nestjs/testing';
import { getRepositoryToken } from '#nestjs/typeorm';
import { QuestsService } from 'src/quests/quests.service';
import { QuestRepository } from 'src/quests/repositories/quest.repository';
import { Repository } from 'typeorm';
import { Complete } from 'src/quests/entities/complete.entity';
import { Player } from 'src/players/entities/player.entity';
const mockRepository = () => ({
create: jest.fn(),
save: jest.fn(),
findOne: jest.fn(),
});
const mockQuestsRepository = {
save: jest.fn(),
findOne: jest.fn(),
findAllWithCompletes: jest.fn(),
findOneWithCompletes: jest.fn(),
};
type MockRepository<T = any> = Partial<Record<keyof Repository<T>, jest.Mock>>;
type MockQuestRepository = Partial<Record<keyof QuestRepository, jest.Mock>>;
describe('QuestsService', () => {
let service: QuestsService;
let playersRepository: MockRepository<Player>;
let completeRepository: MockRepository<Complete>;
let questsRepository: MockQuestRepository;
beforeAll(async () => {
const module = await Test.createTestingModule({
providers: [
QuestsService,
{
provide: getRepositoryToken(Player),
useValue: mockRepository(),
},
{
provide: getRepositoryToken(Complete),
useValue: mockRepository(),
},
{
provide: QuestRepository,
useValue: mockQuestsRepository,
},
],
}).compile();
service = module.get<QuestsService>(QuestsService);
playersRepository = module.get(getRepositoryToken(Player));
completeRepository = module.get(getRepositoryToken(Complete));
questsRepository = module.get(QuestRepository);
});
describe('questComplete', () => {
it('should fail if quest does not exist', async () => {
questsRepository.findOne.mockResolvedValue(undefined);
const result = await service.questComplete(-1, 1);
expect(result).toEqual({
ok: false,
message: 'cant find requested Quest.',
});
});
it('should fail if player does not exist', async () => {
questsRepository.findOne.mockResolvedValue(true);
playersRepository.findOne.mockResolvedValue(undefined);
const result = await service.questComplete(1, 1);
expect(result).toEqual({
ok: false,
message: 'cant find player.',
});
});
});
});
quests.service.ts
#Injectable()
export class QuestsService {
constructor(
#InjectRepository(Complete)
private readonly completes: Repository<Complete>,
private readonly quests: QuestRepository
) {}
async questComplete(questId: number, playerId: number) {
try {
const quest = await this.quests.findOne({ id: questId });
if (!quest)
return { ok: false, message: 'cant find requested Quest.' };
const player = await Player.findOne({ where: { id: playerId } });
if (!player)
return { ok: false, message: 'cant find player.' };
const isCompleted = await this.completes.findOne({ quest, player });
if (isCompleted)
return { ok: false, message: 'quest is already completed.' };
await this.completes.save(this.completes.create({ quest, player }));
return { ok: true };
} catch (error) {
return { ok: false, message: 'quest cant be completed.' };
}
}
}
Using Jest, I would like to mock one of my dependencies, but I would like to spy on the properties that mock is returning. For example, something like:
const mockGet = jest.fn(() => {});
const mockPost = jest.fn(() => {});
const mockDel = jest.fn(() => {});
jest.mock('../../services/MyService', () => {
return {
mockGet,
mockPost,
mockDel
};
});
// ...
describe('MyService', () => {
it('should do something', () => {
myService.doThis();
expect(mockGet).toHaveBeenCalled();
});
});
The problem is this gives an error jest.mock() is not allowed to reference any out-of-scope variables.
The only way I can get it to work so far is by defining the mocks inside the call to jest.mock:
jest.mock('../../services/MyService', () => {
return {
mockGet: jest.fn(() => {}),
mockPost: jest.fn(() => {}),
mockDel: jest.fn(() => {})
};
});
But then how do I access the properties to see if they were called?
Here is the solution:
Service.ts:
class Service {
public get() {
return 'real data';
}
public post() {}
public del() {}
public doThis() {
console.log('real do this');
return this.get();
}
}
export { Service };
Service.spec.ts:
import { Service } from './service';
const service = new Service();
// console.log(service);
jest.mock('./service.ts', () => {
const originalModule = jest.requireActual('./service.ts');
const { Service: OriginalService } = originalModule;
const ServiceMocked = {
...OriginalService.prototype,
get: jest.fn(),
post: jest.fn(),
del: jest.fn()
};
return {
Service: jest.fn(() => ServiceMocked)
};
});
describe('Service', () => {
it('should do something', () => {
service.get = jest.fn().mockReturnValueOnce('mocked data');
const actualValue = service.doThis();
expect(actualValue).toBe('mocked data');
expect(service.get).toHaveBeenCalled();
});
});
Unit test result:
PASS src/stackoverflow/57172774/service.spec.ts
Service
✓ should do something (11ms)
console.log src/stackoverflow/57172774/service.ts:6
real do this
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 1.336s, estimated 3s
I have a method that check if request query string has some params:
checkMandatoryQueryParams (mandatoryQueryParams: String[], req: Request): void {
let result = true;
mandatoryQueryParams.forEach((element, idx) => {
if (!req.query.hasOwnProperty(element)) {
result = false;
}
});
return result;
}
in unit-testing i need to mock the request for test it, eg:
describe('Utils', () => {
it('checkMandatoryQueryParams', () => {
const req: Request = new Request(); // pseudo-code
req.query = "?foo=test&bar=test"; // pseudo-code
expect( checkMandatoryQueryParams(['foo', 'bar'], req) ).toEqual(true);
});
});
how can i mock the express request?
Two options:
Create your own mock object:
describe('Utils', () => {
/**
* Mocked Express Request object
*/
let mockedReq;
beforeEach(() => {
mockedReq = {
query: {}
};
})
it('checkMandatoryQueryParams', () => {
const req = mockedReq;
req.query = "?foo=test&bar=test"; // pseudo-code
expect(checkMandatoryQueryParams(['foo', 'bar'], req) ).toEqual(true);
});
});
Use manual mocks, similar to above:
describe('Utils', () => {
/**
* Mocked Express Request object
*/
let mockedReq;
beforeAll(() => {
mockedReq = jest.fn().mockImplementation(() => {
const req = {
// Implementation
};
return req;
});
});
beforeEach(() => mockedReq.mockReset())
it('checkMandatoryQueryParams', () => {
const req = mockedReq;
req.query = "?foo=test&bar=test"; // pseudo-code
expect(checkMandatoryQueryParams(['foo', 'bar'], req) ).toEqual(true);
});
});
I'm having troubles stubbing out an async action for redux-thunk. Mocha keeps giving me timeout:
// actions.js
const fetchUserThings = userId => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve([{ foo: 'bar' }]);
}
});
};
const displayUserThings = userThings => ({
type: 'DISPLAY',
userThings
});
export const loadUserThings = userId => {
return dispatch => {
fetchUserThings(userId)
.then(userThings => displayUserThings(userThings));
};
}
And here's my mocha test. I'm using redux on version 3.3.1 and redux-mock-store on version 0.0.6.
import configureMockStore from 'redux-mock-store';
import thunk from 'redux-thunk';
import * as actions from './actions';
const middlewares = [thunk];
const mockStore = configureMockStore(middlewares);
describe('actions', () => {
it('creates DISPLAY after fetching', done => {
const userId = 1;
const userThings = [{ foo: 'bar' }];
const expectedActions = [
{ type: 'DISPLAY', userThings }
];
const store = mockStore({userThings: []}, expectedActions, done);
store.dispatch(actions.loadUserThings(userId);
});
});
What am I missing?