2021-12-10

Tech Programing

程式人小天地

How to mock authentication isAuthenticate using Spring Security, JWT and Mockito

2 min read


I’m trying to use Mockito to test whether when the user hits the login api, it will respond with a JWT token. However, I keep getting the Bad Credentials error which comes from the Authentication.authenticate() method inside Spring Security. I’m now trying to mock this method but I keep getting a variety of different errors and not sure if my approach is correct. This is my latest implementation, which now fails with You cannot use argument matchers outside of verification or stubbing as it’s not liking how I’m using the mocks.

@WebMvcTest(value = UserCommandController.class, includeFilters = {
    // to include JwtUtil in spring context
    @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = JwtUtil.class)})
class UserCommandControllerTest {

Logger logger = LoggerFactory.getLogger(UserCommandControllerTest.class);

@MockBean
private UserCommandService userCommandService;

@Autowired
private MockMvc mockMvc;

@MockBean
private UserDetailsServiceImpl userDetailsServiceImpl;

@MockBean
private JwtUtil jwtUtil;

@Autowired
private JwtRequestFilter jwtRequestFilter;

@Autowired
AuthenticationManager authenticationManager;

private static UserDetails dummy;
private static String jwtToken;

@BeforeEach
public void setUp() {
    dummy = new User("[email protected]", "123456", new ArrayList<>());
    jwtToken = jwtUtil.generateToken(dummy);
}


@Test
void testLoginReturnsJwt() throws Exception {

    AuthenticationRequest authenticationRequest = new AuthenticationRequest("[email protected]", "123456");
    AuthenticationResponse authenticationResponse = new AuthenticationResponse("124");

    String jsonRequest = asJsonString(authenticationRequest);
    String jsonResponse = asJsonString(authenticationResponse);

    RequestBuilder request = MockMvcRequestBuilders
            .post("/api/adverts/user/login")
            .content(jsonRequest)
            .contentType(MediaType.APPLICATION_JSON_VALUE)
            .accept(MediaType.APPLICATION_JSON);

    Authentication authentication = mock(Authentication.class);
    authentication.setAuthenticated(true);
    when(authentication.isAuthenticated()).thenReturn(true);

    when(authenticationManager.authenticate(any())).thenReturn(authentication); // Failing here

    when(jwtUtil.generateToken(dummy)).thenReturn("124");
    when(userDetailsServiceImpl.loadUserByUsername(eq("[email protected]"))).thenReturn(dummy);

    MvcResult mvcResult = mockMvc.perform(request)
            .andExpect(status().is2xxSuccessful())
            .andExpect(content().json(jsonResponse, true))
            .andExpect(jsonPath("$.jwt").value(isNotNull()))
            .andReturn();

    logger.info(mvcResult.getResponse().getContentAsString());
}

Here is my controller:

@PostMapping(value = "/login", produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Object> loginUser(@Valid @RequestBody AuthenticationRequest authenticationRequest) throws Exception {

    try {
        Authentication authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(authenticationRequest.getUsername(), authenticationRequest.getPassword()));
    } catch (BadCredentialsException e) {
        throw new Exception("incorrect username or password", e);
    }

    UserDetails userDetails = userDetailsService.loadUserByUsername(authenticationRequest.getUsername());

    String jwt = jwtTokenUtil.generateToken(userDetails);

    return ResponseEntity.ok(new AuthenticationResponse(jwt));
}

Thank you.



Source link

資料來源:Stackoverflow

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *