title: @WithUserDetails failing because username not found
body: <p>I am trying to make a test for my <code>AuthController.java</code> but it keeps failing saying that the username is not found. I have narrowed this problem down to the line in <code>UserService.java</code> that checks if <code>foundUser == null</code>.</p>
  <p>Here is my <code>AuthControllerTests.java</code></p>
  <pre><code>package dev.tdwl.controller;
  
  import dev.tdwl.repository.CategoryListsRepository;
  import dev.tdwl.repository.UserRepository;
  import dev.tdwl.security.jwt.JwtUtils;
  import dev.tdwl.services.UserService;
  import org.junit.jupiter.api.Test;
  import org.springframework.beans.factory.annotation.Autowired;
  import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
  import org.springframework.boot.test.context.SpringBootTest;
  import org.springframework.boot.test.mock.mockito.MockBean;
  import org.springframework.security.authentication.AuthenticationManager;
  import org.springframework.security.crypto.password.PasswordEncoder;
  import org.springframework.security.test.context.support.WithUserDetails;
  import org.springframework.test.web.servlet.MockMvc;
  
  import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
  import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
  import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
  
  @SpringBootTest(classes = {AuthController.class, UserService.class})
  @AutoConfigureMockMvc
  public class AuthControllerTests {
  
      @Autowired
      private MockMvc mockMvc;
  
      @MockBean
      private PasswordEncoder encoder;
  
      @MockBean
      private JwtUtils jwtUtils;
  
      @MockBean
      private AuthenticationManager authenticationManager;
  
      @MockBean
      private CategoryListsRepository categoryRepo;
  
      @MockBean
      private UserRepository userRepository;
  
      @Test
      @WithUserDetails(value = &quot;testuser&quot;, userDetailsServiceBeanName = &quot;userService&quot;)
      void testAuthenticationCheckValid() {
          try {
              mockMvc.perform(get(&quot;/auth/check&quot;)).andExpect(status().isOk()).andDo(print());
          } catch (Exception e) {
              e.printStackTrace();
          }
      }
  }
  </code></pre>
  <p>And my <code>AuthController.java</code></p>
  <pre><code>package dev.tdwl.controller;
  
  
  import com.mongodb.MongoException;
  import dev.tdwl.model.AuthenticationRequest;
  import dev.tdwl.model.CategoryLists;
  import dev.tdwl.model.JwtResponse;
  import dev.tdwl.model.User;
  import dev.tdwl.repository.CategoryListsRepository;
  import dev.tdwl.repository.UserRepository;
  import dev.tdwl.security.jwt.JwtUtils;
  import dev.tdwl.services.UserDetailsImpl;
  import org.springframework.beans.factory.annotation.Autowired;
  import org.springframework.dao.DuplicateKeyException;
  import org.springframework.http.HttpStatus;
  import org.springframework.http.ResponseEntity;
  import org.springframework.security.authentication.AuthenticationManager;
  import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
  import org.springframework.security.core.Authentication;
  import org.springframework.security.core.context.SecurityContextHolder;
  import org.springframework.security.crypto.password.PasswordEncoder;
  import org.springframework.web.bind.annotation.GetMapping;
  import org.springframework.web.bind.annotation.PostMapping;
  import org.springframework.web.bind.annotation.RequestBody;
  import org.springframework.web.bind.annotation.RestController;
  
  import java.util.Collections;
  
  @RestController
  public class AuthController {
  
      private CategoryListsRepository categoryRepo;
      private UserRepository userRepo;
      private AuthenticationManager authenticationManager;
      private PasswordEncoder encoder;
      private JwtUtils jwtUtils;
  
      @Autowired
      public AuthController(UserRepository repository, AuthenticationManager authenticationManager, PasswordEncoder encoder, JwtUtils jwtUtils, CategoryListsRepository categoryRepo) {
          this.authenticationManager = authenticationManager;
          this.userRepo = repository;
          this.encoder = encoder;
          this.jwtUtils = jwtUtils;
          this.categoryRepo = categoryRepo;
      }
  
      @GetMapping(&quot;/auth/check&quot;)
      public ResponseEntity&lt;?&gt; verifyLogin() {
          UserDetailsImpl userDetails = (UserDetailsImpl) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
  
          if (userDetails.getId() == null) {
              return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
          }
  
          return ResponseEntity.ok(userDetails);
      }
  
      @PostMapping(&quot;/auth/login&quot;)
      public ResponseEntity&lt;?&gt; login(@RequestBody AuthenticationRequest authenticationRequest) {
          Authentication authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(authenticationRequest.getEmail(), authenticationRequest.getPassword()));
          SecurityContextHolder.getContext().setAuthentication(authentication);
          String jwt = jwtUtils.generateJwtToken(authentication);
  
          UserDetailsImpl user = (UserDetailsImpl) authentication.getPrincipal();
          return ResponseEntity.ok(new JwtResponse(jwt, user.getUsername(), user.getId()));
      }
  
      @PostMapping(&quot;/auth/signup&quot;)
      public ResponseEntity&lt;?&gt; authenticateClient(@RequestBody AuthenticationRequest authenticationRequest) {
          String email = authenticationRequest.getEmail();
          String password = authenticationRequest.getPassword();
  
          User newUser = new User(email, encoder.encode(password));
  
          try {
              userRepo.save(newUser);
              CategoryLists newList = new CategoryLists(newUser.getId(), Collections.emptyList());
              categoryRepo.save(newList);
          } catch (DuplicateKeyException | MongoException e) {
              return ResponseEntity.status(HttpStatus.CONFLICT).build();
          }
  
          return ResponseEntity.ok(&quot;User registered successfully!&quot;);
      }
  }
  
  </code></pre>
  <p>and my <code>UserService.java</code></p>
  <pre><code>package dev.tdwl.services;
  
  import dev.tdwl.model.User;
  import dev.tdwl.repository.UserRepository;
  import org.springframework.beans.factory.annotation.Autowired;
  import org.springframework.security.core.userdetails.UserDetails;
  import org.springframework.security.core.userdetails.UserDetailsService;
  import org.springframework.security.core.userdetails.UsernameNotFoundException;
  import org.springframework.stereotype.Service;
  
  @Service
  public class UserService implements UserDetailsService {
  
      private final UserRepository userRepository;
  
      @Autowired
      public UserService(UserRepository userRepository) {
          this.userRepository = userRepository;
      }
  
      @Override
      public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
          User foundUser = userRepository.findUserByEmail(username);
          if (foundUser == null) throw new UsernameNotFoundException(&quot;User not found.&quot;);
  
          return UserDetailsImpl.build(foundUser);
      }
  }
  </code></pre>
  <p>The line this is failing on is in <code>UserService.java</code> where it tries to findUserByEmail, because userRepository is mocked it just returns null and throws the username not found exception. If I remove the Mock, then my test fails because it couldn't find the UserRepository bean required for the constructor in <code>AuthController</code></p>
  <p>Any ideas on how to do this correctly?</p>