There’s a longish discussion about how to do this in this issue.
I’ve experimented with a number of the proposed solutions but I’m not having much luck.
Could anyone provide a concrete example of how to test a service with an injected repository and mock data?
Advertisement
Answer
Let’s assume we have a very simple service that finds a user entity by id:
JavaScript
x
9
1
export class UserService {
2
constructor(@InjectRepository(UserEntity) private userRepository: Repository<UserEntity>) {
3
}
4
5
async findUser(userId: string): Promise<UserEntity> {
6
return this.userRepository.findOne(userId);
7
}
8
}
9
Then you can mock the UserRepository
with the following mock factory (add more methods as needed):
JavaScript
1
6
1
// @ts-ignore
2
export const repositoryMockFactory: () => MockType<Repository<any>> = jest.fn(() => ({
3
findOne: jest.fn(entity => entity),
4
// ...
5
}));
6
Using a factory ensures that a new mock is used for every test.
JavaScript
1
26
26
1
describe('UserService', () => {
2
let service: UserService;
3
let repositoryMock: MockType<Repository<UserEntity>>;
4
5
beforeEach(async () => {
6
const module: TestingModule = await Test.createTestingModule({
7
providers: [
8
UserService,
9
// Provide your mock instead of the actual repository
10
{ provide: getRepositoryToken(UserEntity), useFactory: repositoryMockFactory },
11
],
12
}).compile();
13
service = module.get<UserService>(UserService);
14
repositoryMock = module.get(getRepositoryToken(UserEntity));
15
});
16
17
it('should find a user', async () => {
18
const user = {name: 'Alni', id: '123'};
19
// Now you can control the return value of your mock's methods
20
repositoryMock.findOne.mockReturnValue(user);
21
expect(service.findUser(user.id)).toEqual(user);
22
// And make assertions on how often and with what params your mock's methods are called
23
expect(repositoryMock.findOne).toHaveBeenCalledWith(user.id);
24
});
25
});
26
For type safety and comfort you can use the following typing for your (partial) mocks (far from perfect, there might be a better solution when jest itself starts using typescript in the upcoming major releases):
JavaScript
1
4
1
export type MockType<T> = {
2
[P in keyof T]?: jest.Mock<{}>;
3
};
4