'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