Reputation: 3255
I have a Spring Boot 2 web service. It accepts a Bearer token and uses Spring OAuth2 to go to an external URL and grab the users details using that token. I'm trying to create tests that test the implementation of the web service, but I'm struggling to figure out how to pass the AuthenticationPrinicple from a test?
Here is an example of a method in my controller;
@RequestMapping(value = "", method = RequestMethod.GET, produces = "application/json")
public ResponseEntity listUserUploadedFiles(@AuthenticationPrincipal Client client) {
FileListResponse rsp = new FileListResponse(fileStorageService.getUserFiles(client.getUid()));
return rsp.response(HttpStatus.OK);
}
Here is my test so far;
@Test
public void TestSimple() throws Exception {
mockMvc.perform(get("/file"))
.andExpect(status().isOk());
}
Currently the test fails because the Client (AuthenticationPrinicple) is null.
How would I do this?
---- UPDATE ----
Here is my Client object, as you can see, it doesn't inherit UserDetails.
public class Client implements Serializable {
private static final long serialVersionUID = 1L;
private String uid;
private String email;
public String getUid() {
return uid;
}
public void setUid(String uid) {
this.uid = uid;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
There is also a PrincipalExtractor bean setup.
@Bean
public PrincipalExtractor principalExtractor() {
return map -> {
Client client = new Client();
client.setUid(String.valueOf(map.get("uid")));
client.setEmail(String.valueOf(map.get("name")));
return client;
};
}
To provide a little more information on the project. This is a microservice, the user authenticates via a web application which takes place externally to this service. When calls to this server are made, a token is supplied which is verified with an authenticate server (again, external). The response from authentication server provides us with a uuid and an email field, the PrincipalExtractor maps these to a Client object, which is then passed into the controller to be used.
Upvotes: 1
Views: 800
Reputation: 6936
You could mock your user when testing @WithMockUser
.
If you use MockMvc there is no extra sec-config needed
@RunWith(SpringRunner.class)
@WebMvcTest(SecuredController.class)
public class SecuredControllerWebMvcIntegrationTest {
@Autowired
private MockMvc mockMvc;
@Test
@WithMockUser(value = "user")
public void testSimple() throws Exception {
mockMvc.perform(get("/file"))
...
if you want to use @WithMockUser
in a @SpringBootTest
you need extra configuration
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class SecuredControllerSpringBootIntegrationTest
...
@Autowired
private WebApplicationContext context;
private MockMvc mvc;
@Before
public void setup() {
mvc = MockMvcBuilders
.webAppContextSetup(context)
.apply(springSecurity())
.build();
}
...
ref spring-security-integration-tests
Upvotes: 1