Search code examples
javaspring-bootjunitmockito

findById doesn't see the object from the mock


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?


Solution

  • 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.