Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JUNIT5 @InjectMocks throws NullPointerException

This is my first project using TDD and JUNIT 5. I am using latest Springboot for my project.

I have noticed that when I have dependencies coming from springboot, they are not getting injected during test phase when using @InjectMocks annotation. I am getting NullPointerException for authenticationManager dependency. However, the test passes when the service method only uses a repository dependency created using springboot JPA for entity class.

Below is the service class and the corresponding test class. UserServiceImpl.java

@Service
public class UserServiceImpl implements UserService {

@Autowired
AuthenticationManager authenticationManager;

@Autowired
UserRepository userRepository;

@Autowired
PasswordEncoder passwordEncoder;

@Autowired
UserDetailsService userDetailsService;

@Autowired
JWTUtil jwtUtil;

@Override
@Transactional
public AuthenticationResponseDTO login(AuthenticationRequestDTO authenticationRequestDTO) {
    try {
        authenticationManager.authenticate(
                new UsernamePasswordAuthenticationToken(authenticationRequestDTO.getUserName(), authenticationRequestDTO.getPassword()));

        UserDetails userDetails = userDetailsService.loadUserByUsername(authenticationRequestDTO.getUserName());

        return new AuthenticationResponseDTO(userDetails.getUsername(), jwtUtil.generateToken(userDetails));
    }
    catch (BadCredentialsException e) {
        throw e;
    }
}

UserServiceImplTest.java

@InjectMocks
private UserServiceImpl userServiceImpl;

@Mock
private UserRepository userRepository;

private User userMock;

private AuthenticationRequestDTO authenticationRequestDTO;

@BeforeEach
void init(){
    MockitoAnnotations.initMocks(this);
}

@BeforeEach
void setupUser(){
    userMock = new User();
    userMock.setUserName("sd");
    userMock.setPassword("sd");

    authenticationRequestDTO = new AuthenticationRequestDTO();
    authenticationRequestDTO.setUserName("sd");
    authenticationRequestDTO.setPassword("sd");
}

@Test
void testUserIsPresentOrNot(){

    Mockito.when( userRepository.findByUserName("sd") ).thenReturn(userMock);

    AuthenticationResponseDTO responseDTO = userServiceImpl.login(authenticationRequestDTO);

    assertNotNull(responseDTO);
    assertEquals(userMock.getUserName(), responseDTO.getName(), "user id should be same.");
}

Please let me know if further details are needed from my end.

like image 282
sd1517 Avatar asked Jun 06 '26 00:06

sd1517


1 Answers

I am not sure I am 100% following, as match as I can see you are missing some annotations.

If you want to inject Spring beans in a Unit test you need @SpringBootTest/@ExtendWith(SpringExtension.class) (Making it integration test from my point of view).

If you want to use Mockito @InjectMocks and @Mock require @ExtendWith(MockitoExtension.class) above the test class.

And delete the following.

@BeforeEach
void init(){
    MockitoAnnotations.initMocks(this);
}

Mixing both dependency injection with spring and Mockito will be too complicate from my point of view. I would prefer to use only Mockito for unit tests.

Maybe the following article can help.

like image 146
Haim Raman Avatar answered Jun 10 '26 10:06

Haim Raman



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!