1

Similar to Authentication token passed to ControllerAdvice is null when running through MockMvc, my MockMvc tests for a Spring Boot 1.5.16 application with Spring Data REST and Spring Security always have a null Authentication parameter whether I add the context manually or with @WithUserDetails.

Is this a bug in Spring Security's testing code, or am I messing up somewhere?

The @RepositoryRestController methods look like:

@PostMapping("/resources/{id}/attributes")
public @ResponseBody ResponseEntity<?> attributes(
    @PathVariable("id") long resourceId, 
    @RequestParam(value = "file", required = true) MultipartFile file,
    Authentication authentication ) throws IOException {

    // 2.
    Subject.setAuthentication(authentication);

    try (InputStream input = file.getInputStream()) {
        attributeHandler.read(resourceId, file.getName(), input);
    }

    return ResponseEntity.ok(success());
}

and my MockMvc tests look like:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
@AutoConfigureMockMvc
public class RestControllerTest {
    private MockMvc mockMvc;

    @Autowired
    private WebApplicationContext webApplicationContext;

    @Before
    public void setup() throws Exception {
        this.mockMvc = webAppContextSetup(webApplicationContext)
                .apply(springSecurity())
                .build();
    }

    @Test
    @WithUserDetails("myAttributeManagerUsername")
    public void attributes() throws Exception {     

        // 1.
        Authentication authentication = 
            SecurityContextHolder.getContext().getAuthentication();

        mockMvc.perform(
            MockMvcRequestBuilders.fileUpload(
                "/api/resources/1/attributes"
            ).file(attributesFile())
            // 3. .with(authentication(authentication)))
        .andExpect(status().isOk());
    }
}

Within the test method (at 1.) I have verified that authentication is present, but when the controller method is called (at 2.) the authentication is null, even if I manually set the context (at 3.) via .sessionAttr() or .with() (as shown). When running the application outside of the tests, the controller methods do get a proper authentication token (at 2.) with authenticated subjects.

Any ideas what's wrong in my tests?

Jan Nielsen
  • 10,892
  • 14
  • 65
  • 119
  • 1
    As far as what you have posted here, I've replicated your posted code in a GitHub sample: https://github.com/jzheaux/so-53875541 where the test passes. Perhaps there is some additional configuration that you have not posted? – jzheaux Dec 21 '18 at 21:02
  • ^^^ Nice @jzheaux! Looks like you're right - I'm playing with your sample and my application to narrow down the problem (looks like it's somewhere in my user details + service implementations). I'll report next week. I owe you a beer. – Jan Nielsen Dec 21 '18 at 23:46

1 Answers1

0

Gee. This is not likely to be particularly helpful but...

As part of my (not shown) infrastructure, a filter incorrectly reset the authentication prior to the API which triggered this bug.

Sorry about the noise.

Jan Nielsen
  • 10,892
  • 14
  • 65
  • 119