I am writing a test for the UserServiceImpl service.
public User getUserById(long id) {
Optional<User> optional = userRepository.findById(id);
User user = null;
if (optional.isPresent()) {
user = optional.get();
} else {
throw new RuntimeException("User not found for id: " + id);
}
return user;
}
UserServiceImplTest
@ExtendWith(MockitoExtension.class)
public class UserServiceImplTest {
@Mock
private UserRepository userRepository;
@InjectMocks
private UserServiceImpl userService;
@Test
public void shouldReturnUserById() {
List<User> users = getUsers();
Long id = 1L;
Mockito.when(userRepository.findAll()).thenReturn(users);
System.out.println(users.get(0).getId());
User result = userService.getUserById(id);
Assertions.assertNotNull(result);
Assertions.assertEquals(users.get(0), result);
}
private List<User> getUsers() {
User firstUser = new User();
User secondUser = new User();
firstUser.setId(1L);
firstUser.setName("Rob");
firstUser.setLastName("King");
firstUser.setDepartment("Supply");
firstUser.setPosition("Team lead");
secondUser.setId(2L);
secondUser.setName("Mike");
secondUser.setLastName("Wilson");
secondUser.setDepartment("Sale");
secondUser.setPosition("Specialist");
return List.of(firstUser, secondUser);
}
}
When running a test in the userService.getUserById(id) method - java.lang.RuntimeException: User not found for id: 1 Although there is an object with the same ID in the repository. Tell me please what did I miss?
The main issue here is that you're mocking userRepository.findAll()
instead of userRepository.findById(id)
.
In your UserServiceImpl
implementation, you're using findById(id)
to fetch the user, but in the test, you've set up a mock for findAll()
. These are two different methods, and Mockito doesn't know how to respond when findById(id)
is called because it hasn't been instructed on what to do in that scenario.
To fix this, you'll want to mock the behavior of findById(id)
. Here's how you can do it:
Mockito.when(userRepository.findById(eq(1L))).thenReturn(Optional.of(getUsers().get(0)));
Notice the eq
method which provides you the ability to match specific arguments passed to your mock.
Please be aware that this test, given the simplicity of your service layer, may not be testing meaningful behavior as it mocks the repository and does not cover real database interactions, potentially missing integration issues.