javaspringjunitjunit5springmockito

Mock object is null in JUnit Test


I design the test in JUnit using Mockito. The problem is in the following Test:

@ExtendWith(MockitoExtension.class)
class UserServiceTest {
    
    @InjectMocks
    private UserService userService;
    @Mock
    private UserDAO userDAO;
    @Mock
    private ModelMapper modelMapper;
    @Mock
    private UserDTOMapper userDTOMapper;

    private User user;
    private UserDTO userDTO;

    private AutoCloseable closeable;

    @BeforeTestMethod
    public void initMocks(){
        MockitoAnnotations.openMocks(this);
    }

    @BeforeEach
    void setUp() {
        userDTO = UserDTO.builder()
                .username("johnny")
                .firstname("John")
                .surname("Rogers")
                .email("john@gmail.com")
                .phoneNumber("0123456789")
                .role(Role.ADMIN).build();
        user = User.builder()
                .username("johnny")
                .password("johnny123")
                .firstname("John")
                .surname("Rogers")
                .email("john@gmail.com")
                .phoneNumber("0123456789")
                .role(Role.ADMIN).build();
    }

    @Test
    void findUser() {
        userDao.sace(user);
        assertEquals(userDTO, userService.findUser(user.getUsername()));
    }

    @Test
    void convertToDto() {
        assertEquals(userDTO, userDTOMapper.apply(user));
    }


    @AfterTestMethod
    public void releaseMocks() throws Exception {
        closeable.close();
    }
}

The test is for this service class:

@Service
@RequiredArgsConstructor
public class UserService {

    private final UserDAO userDAO;
    private final ModelMapper modelMapper;
    private final UserDTOMapper userDTOMapper;

    public UserDTO findUser(String username) {
        User user = userDAO.findUserByUsername(username);
        return userDTOMapper.apply(user);
    }

    public UserDTO convertToDto(User user) {
        return modelMapper.map(user, UserDTO.class);
    }
}

Error:

org.opentest4j.AssertionFailedError: 
Expected :UserDTO(id=0, username=johnny, firstname=John, surname=Rogers, email=john@gmail.com, phoneNumber=0123456789, role=USER)
Actual   :null
<Click to see difference>


    at org.junit.jupiter.api.AssertionFailureBuilder.build(AssertionFailureBuilder.java:151)
    at org.junit.jupiter.api.AssertionFailureBuilder.buildAndThrow(AssertionFailureBuilder.java:132)
    at org.junit.jupiter.api.AssertEquals.failNotEqual(AssertEquals.java:197)
    at org.junit.jupiter.api.AssertEquals.assertEquals(AssertEquals.java:182)
    at org.junit.jupiter.api.AssertEquals.assertEquals(AssertEquals.java:177)
    at org.junit.jupiter.api.Assertions.assertEquals(Assertions.java:1142)

I'm not really sure what's the problem or am I doing something wrong? At first, I thought that the problem is in "@RequiredArgsConstructor" annotation, but that's not a problem. I'm sure that the solution is something simple, but I don't really understand why all the mocked objects are NULL


Solution

    1. You don't need to use openMocks(). The annotation @ExtendWith(MockitoExtension.class) already did it for you.
    2. You didn't stub any of the behavior for your dependencies.
    3. Remove after and before methods. if you want to create Instances for your User and Dto just use private methods. You do not need to create it after every test.

    Here is my example of how it should look. If it worked then you can start refactoring:

    @ExtendWith(MockitoExtension.class)
    public class UserServiceTest {
    
        @Mock
        private UserDAO userDAO;
    
        @Mock
        private ModelMapper modelMapper;
    
        @InjectMocks
        private UserService userService;
    
        @Test
        public void testFindUser() {
            // Arrange
            String username = "testUser";
            User user = User.builder()
                    .id(1)
                    .username(username)
                    .firstname("John")
                    .surname("Doe")
                    .email("johndoe@example.com")
                    .phoneNumber("123456789")
                    .role(Role.USER)
                    .build();
            when(userDAO.findUserByUsername(username)).thenReturn(user);
    
            UserDTO expectedDto = UserDTO.builder()
                    .id(1)
                    .username(username)
                    .firstname("John")
                    .surname("Doe")
                    .email("johndoe@example.com")
                    .phoneNumber("123456789")
                    .role(Role.USER)
                    .build();
            when(userDTOMapper.apply(user)).thenReturn(expectedDto);
            
            UserDTO result = userService.findUser(username);
            
            assertEquals(expectedDto, result);
        }
    
        @Test
        public void testConvertToDto() {
            // Arrange
            User user = User.builder()
                    .id(1)
                    .username("testUser")
                    .firstname("John")
                    .surname("Doe")
                    .email("johndoe@example.com")
                    .phoneNumber("123456789")
                    .role(Role.USER)
                    .build();
    
            UserDTO expectedDto = UserDTO.builder()
                    .id(1)
                    .username("testUser")
                    .firstname("John")
                    .surname("Doe")
                    .email("johndoe@example.com")
                    .phoneNumber("123456789")
                    .role(Role.USER)
                    .build();
    
            when(modelMapper.map(user, UserDTO.class)).thenReturn(expectedDto);
            
            UserDTO result = userService.convertToDto(user);
    
            assertEquals(expectedDto, result);
        }
    

    }