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 situation
Make the repository method return a rejected promise with this exception
Have an existingUser, a fake updateUserDto and an expectedUser, which receives the contents of the existingUser and then of the updateUserDto over them
Have preload() and save() return the expectedUsed
Perform the assertion as usual
describe('when user exists', () => {it('should update the user',async () => {constid=1;constexistingUser=genUser(id);constupdateUserDto=genUpdateDto();constexpectedUser= {...existingUser,...updateUserDto, } asUser;repository.preload.mockResolvedValueOnce(expectedUser);repository.save.mockResolvedValueOnce(expectedUser);constuser=awaitservice.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, by default, they don't return anything. So, when preload() returns undefined, the exception will be thrown, similarly to when the user is not found.
Here, toEqual() is used instead of toBe() because, remember that the exception is a composite type. With primitive types only the value matters, but for composite types the reference is also important. So, as in this case it's not this exact exception that will be thrown, but another one that is identical to it, we need to use toEqual() to check if our exception here has the same shape of the one being thrown, whereas using toBe() would check if they are the exact same exception, which is not the case here.
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 () => {constid=1;constexpectedUser=genUser(id);jest.spyOn(service,'findOne').mockResolvedValueOnce(expectedUser);repository.remove.mockResolvedValueOnce(expectedUser);constuser=awaitservice.remove(id);expect(user).toBe(expectedUser); });});