Remaining service tests
We already have a structure to easily implement the remaining tests.
Inside the describe()
for the findOne()
method, we may then have another describe()
below the previous one for when a user
is not found. What we'll do:
Have an
exception
representing this situationMake the
repository
method return a rejected promise with thisexception
Check if the
exception
was propagated
describe('otherwise', () => {
it('should propagate the exception', async () => {
const id = 1;
const exception = new NotFoundException('User not found');
repository.findOneByOrFail.mockRejectedValueOnce(exception);
let error: Error;
try {
await service.findOne(id);
} catch (err) {
error = err;
}
expect(error).toBe(exception);
});
});
Alright, now for findAll()
. This one will be quite simple, we:
Create an array with
expectedUsers
Make the
find()
method of therepository
return themCheck if the obtained
users
match theexpectedUsers
describe('findAll', () => {
it('should return an array of users', async () => {
const expectedUsers = [genUser(1), genUser(2)];
repository.find.mockResolvedValueOnce(expectedUsers);
const users = await service.findAll();
expect(users).toBe(expectedUsers);
});
});
For create()
, let's:
Have a fake
createUserDto
and anexpectedUser
with the contents of this DTOMake the
create()
andsave()
methods of therepository
return them, respectivelyCheck if the result matches the expectation
describe('when no errors occur', () => {
it('should create a user', async () => {
const id = 1;
const createUserDto = genCreateDto();
const expectedUser = genUser(id, createUserDto);
repository.create.mockReturnValueOnce(createUserDto as User);
repository.save.mockResolvedValueOnce(expectedUser);
const user = await service.create(createUserDto);
expect(user).toBe(expectedUser);
});
});
It should also propagate exceptions
, so let's test this too.
describe('otherwise', () => {
it('should propagate exceptions', async () => {
const createUserDto = genCreateDto();
const exception = new ConflictException('Error creating user');
repository.create.mockReturnValueOnce(createUserDto as User);
repository.save.mockRejectedValueOnce(exception);
let error: Error;
try {
await service.create(createUserDto);
} catch (err) {
error = err;
}
expect(error).toBe(exception);
});
});
For update()
, we:
Have an
existingUser
, a fakeupdateUserDto
and anexpectedUser
, which receives the contents of theexistingUser
and then, of theupdateUserDto
over themHave
preload()
andsave()
return theexpectedUsed
Perform the assertion, as usual
describe('when user exists', () => {
it('should update the user', async () => {
const id = 1;
const existingUser = genUser(id);
const updateUserDto = genUpdateDto();
const expectedUser = {
...existingUser,
...updateUserDto,
} as User;
repository.preload.mockResolvedValueOnce(expectedUser);
repository.save.mockResolvedValueOnce(expectedUser);
const user = await service.update(id, updateUserDto);
expect(user).toBe(expectedUser);
});
});
And also check in the case of an exception
. Remember that, in this case, it's the service
itself that throws it and not the repository
. There is no need to mock the return of the repository
methods here because they don't return anything by default. So, when preload()
returns undefined, the exception will be thrown, similarly to when the user
is not found.
describe('otherwise', () => {
it('should throw the adequate exception', async () => {
const id = 1;
const updateUserDto = genUpdateDto();
const exception = new NotFoundException('User not found');
let error: Error;
try {
await service.update(id, updateUserDto);
} catch (err) {
error = err;
}
expect(error).toEqual(exception);
});
});
In the case of remove()
, we have an interesting difference. Here, we call the findOne()
method of the service
itself. It would be interesting to mock it here, as we don't want to have its actual functionality, as it is not the focus of this test. But how could we achieve this, as it is a method from the actual service
and not from a mock? This can be done with the spyOn()
function from Jest. It allows for applying a mocked implementation to a "normal" method through the following form:
describe('when user exists', () => {
it('should remove the user', async () => {
const id = 1;
const expectedUser = genUser(id);
jest.spyOn(service, 'findOne').mockResolvedValueOnce(expectedUser);
repository.remove.mockResolvedValueOnce(expectedUser);
const user = await service.remove(id);
expect(user).toBe(expectedUser);
});
});
We can do the same in the case of an exception
.
describe('otherwise', () => {
it('should propagate the exception', async () => {
const id = 1;
const exception = new NotFoundException('User not found');
jest.spyOn(service, 'findOne').mockRejectedValueOnce(exception);
let error: Error;
try {
await service.remove(id);
} catch (err) {
error = err;
}
expect(error).toBe(exception);
});
});
And we're done! Let's then proceed to the tests for the UsersController
. They will be quite simple.
Last updated