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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With