I'm not able to mock chained function of sequelize. In following example I can mock Query 1, but not Query 2
something.service.ts
// Query 1
await this.table2.findAll<table2>({
attributes: [
'field1'
],
where: {
id: someId
},
});
// Query 2
// returns []
let bill1: any = await this.table2.sequelize.query(`
SELECT
aa.field1,
bg.field2
FROM
table1 aa,
table2 bg
WHERE
bg.id = '${billId}'
AND
aa.id = bg.aggr_id;
`);
something.service.spec.ts
beforeEach(async () => {
const module = await Test.createTestingModule({
providers: [
{
provide: getModelToken(table2),
useValue: {
// mock successful for query 1
findAll: jest.fn(() => [{}]),
// mock fails for query 2
sequelize: jest.fn().mockReturnValue([]),
query: jest.fn().mockReturnValue([]),
'sequelize.query': jest.fn().mockReturnValue([]),
},
}
],
}).compile();
With this code I'm receiving (for Query 2)
TypeError: this.table2.sequelize.query is not a function
I tried with following code, no luck
sequelize: jest.fn().mockReturnValue([]),
query: jest.fn().mockReturnValue([]),
'sequelize.query': jest.fn().mockReturnValue([]),
sequelize: jest.fn().mockReturnValue({
query: jest.fn(() => [])
})
CodePudding user response:
You can utilize jest.fn().mockReturnThis()
to mock the chained function in jest. I have tested this on mocking the TypeORM repository, something like this:
repository.mock.ts
export const mockedRepository = {
find: jest.fn(),
createQueryBuilder: jest.fn(() => ({ // createQueryBuilder contains several chaining methods
innerJoinAndSelect: jest.fn().mockReturnThis(),
getMany: jest.fn(),
})),
};
Somewhere in your service for example:
test.service.ts
//
async findAll(){
return await this.repository
.createQueryBuilder('tableName')
.innerJoinAndSelect('tableName.relation','relation' )
.getMany();
}
//
And finally the unit test spec:
test.service.spec.ts
const module = await Test.createTestingModule({
providers: [
TestService,
{
provide: getRepositoryToken(Test),
useValue: mockedRepository,
}
],
}).compile();
testService =
module.get<TestService>(TestService);
testRepository = module.get<Repository<Test>>(
getRepositoryToken(Test),
);
});
describe('when findAll is called', () => {
beforeEach(() => {
mockedRepository.createQueryBuilder.getMany.mockResolvedValue([]);
});
it('should call innerJoinAndSelect method once', async () => {
await testService.findAll();
expect(mockedRepository.createQueryBuilder.innerJoinAndSelect).toHaveBeenCalledTimes(1);
});
it('should return an empty array', async () => {
expect(await testService.findAll()).toBe([]);
});
});
This is not a real working example but I hope you get the idea.
CodePudding user response:
Issue was with the problem statement itself, this.table.sequelize
is an object NOT a function to be chained, following solution worked to mock it.
sequelize: { query: jest.fn(() => []) }
To mock chained functions Farista's solution works.