I'm using jest with nodejs and sequelize for my models. For my testing, I wanted to mock the returned value of findAll
to cover test scenarios. Sorry if this is a very newbie question but I'm at dead-end on this one.
init-models.js
module.exports = function initModels(sequelize) {
//model relationship code here
...
...
//end of model relationship code
return {
records,
anotherModel,
alsoAnotherModel
};
};
repository.js
const sequelize = require('../sequelize');
const initModels = require('../model/init-models');
let {
records,
anotherModel,
alsoAnotherModel
} = initModels(sequelize);
const fetchRecords = async () => {
console.info('Fetching records...');
return await records.findAll({sequelize parameters here});
}
repository.test.js This will work but needs the flexibility to mock findAll()
return value/or throw Error
const repository = require('../../../src/db/repository/repository');
const initModels = require('../../../src/db/model/init-models');
jest.mock('../../../src/db/model/init-models', () => {
return function() {
return {
records: {
findAll: jest.fn().mockImplementation(() => [1,2,3])
}
//the rest of the code for other models
}
}
});
describe('fetchRecords', () => {
beforeEach(()=> {
});
test('should return correct number of records', async () => {
const result = await repository.fetchRecords();
expect(result.size).toStrictEqual(3); //test passed
});
})
To allow mocking of results of findAll
, I've tried extracting it so I can change the result per test scenario, but it was not working. What did I missed?
const mockRecordsFindAll = jest.fn();
jest.mock('../../../src/db/model/init-models', () => {
return function() {
return {
records: {
findAll: () => mockRecordsFindAll
}
//the rest of the code for other models
}
}
});
describe('fetchRecords', () => {
beforeEach(()=> {
mockRecordsFindAll.mockReset()
});
test('should return correct number of records', async () => {
mockRecordsFindAll.mockImplementation(() => [1,2,3]); //should expect length 3
const result = await repository.fetchRecords();
expect(result.size).toStrictEqual(3); //fails, findAll was not mocked
});
})
CodePudding user response:
The issue is mockRecordsFindAll
is being returned instead of executed.
As @Gid machined just returning mockRecordsFindAll
causes initialization issues (due to hoisting).
The solution for this case is using the decorator pattern
to allow mockRecordsFindAll
to be initialized afterward.
const mockRecordsFindAll = jest.fn();
jest.mock('../../../src/db/model/init-models', () => {
return function() {
return {
records: {
findAll: function () {
return mockRecordsFindAll.call(this, arguments);
}
}
}
}
});
describe('fetchRecords', () => {
...
})