'Test passing when it shouldn't
Authentication method:
@PostMapping("/login")
public ResponseEntity<String> signIn(@RequestBody LoginDto loginDto) {
try {
Authentication authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(
loginDto.getEmail(), loginDto.getPassword()));
SecurityContextHolder.getContext().setAuthentication(authentication);
return new ResponseEntity<>("User signed-in successfully!", HttpStatus.OK);
} catch (BadCredentialsException e) {
return new ResponseEntity<>("Invalid credentials", HttpStatus.UNAUTHORIZED);
}
}
Test:
@Test
void shouldLogin() throws Exception {
LoginDto loginDto = new LoginDto("admin", "ye2esyes");
String expectedMessage = "User signed-in successfully!";
mvc.perform(MockMvcRequestBuilders
.post("/auth/login")
.content(objectMapper.writeValueAsString(loginDto))
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(content().string(expectedMessage));
}
Those are wrong credentials but the test is still passing. When i try to login using postman i actually get 401 with "Invalid credentials" But when i test with Mockmvc it's always passing. I'm using Spring Security
Solution 1:[1]
You need to mock authenticationManager.authenticate to throw BadCredentialsException to make it fails.
Solution 2:[2]
You have to mock the Authentication Manager and that can be done as below code snippet:
Mockito.doThrow(BadCredentialsException.class)
.when(authenticationManager.authenticate(new
UsernamePasswordAuthenticationToken(loginDto.getEmail(), loginDto.getPassword())));
This should work fine !!
Solution 3:[3]
It just turned out that I'm dumb and I forgot that I'm mocking the beans so there isn't actually a connection to the database. I just ended up moving the authentication code to UserService class inside an authenticate() method that returns a boolean, then I stubbed the method and tested the controller and everything is working fine. My test now:
@Test
void shouldReturnUnauthorized() throws Exception{
final LoginDto validLoginDto = new LoginDto("admin", "yesyesyes");
final String expectedMessage = "Invalid credentials";
Mockito.when(userService.authenticate(validLoginDto)).thenReturn(false);
mvc.perform(MockMvcRequestBuilders
.post("/auth/login")
.content(objectMapper.writeValueAsString(validLoginDto))
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isUnauthorized())
.andExpect(content().string(expectedMessage));
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | nnhthuan |
| Solution 2 | Kapil Bablani |
| Solution 3 | GodLike |
