我正在尝试使用SpringBoot + Spring Data Mongo + SpringMVC运行一些集成测试
我已经简化和泛化了代码,但它应该能够通过下面的测试重现该行为。
正如您在BookRepository
界面中看到的那样,我希望用户只能检索他拥有的图书(@Query("{ 'ownerName' : '?#{principal?.username})
),并且我正在编写一个测试来执行POST
来保存图书,然后验证图书的所有者设置是否正确。
为了解决这里的问题,我将测试简化为只使用GET
,然后调用findAll()
问题
执行任何MockMvc
请求后,使用ThreadLocalSecurityContextHolderStrategy#clearContext()
清除SecurityContext
,这会导致在我尝试调用repository.findAll();
时抛出以下异常
java.lang.IllegalArgumentException: Authentication object cannot be null
BookRepository.java
@RepositoryRestResource
public interface BookRepository extends MongoRepository<Book, String> {
@Query("{ 'ownerName' : ?#{principal?.username} }")
List<Book> findAll();
}
BookCustomRepositoryIntegrationTest.java
/**
* Integrate data mongo + mvc
*/
@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class BookCustomRepositoryIntegrationTest {
@Autowired
BookRepository repository;
@Autowired
MockMvc mockMvc;
@Test
@WithMockUser
public void reproduceBug() throws Exception {
repository.findAll(); //Runs allright
mockMvc.perform(get("/books")
.contentType(APPLICATION_JSON_UTF8))
.andExpect(status().isOk());
repository.findAll(); //Throws exception: java.lang.IllegalArgumentException: Authentication object cannot be null
}
}
发布于 2018-08-18 00:18:27
您的情况不起作用,因为SecurityContextPersistenceFilter和FilterChainProxy筛选器清除了SecurityContextHolder,但TestSecurityContextHolder
(由WithSecurityContextTestExecutionListener
填充)仍包含SecurityContext。
尝试以下方法:
@Test
@WithMockUser
public void reproduceBug() throws Exception {
repository.findAll();
mockMvc.perform(get("/books")
.contentType(APPLICATION_JSON_UTF8))
.andExpect(status().isOk());
SecurityContextHolder.setContext(TestSecurityContextHolder.getContext());
repository.findAll();
}
发布于 2021-03-31 15:47:19
我刚刚找到了这个问题的一个很好的解决方案。您可以在测试配置中注册MockMvcBuilderCustomizer bean,一切工作正常。
public class MockMvcTestSecurityContextPropagationCustomizer implements MockMvcBuilderCustomizer {
@Override
public void customize(ConfigurableMockMvcBuilder<?> builder) {
builder.alwaysDo(result -> {
log.debug("resetting SecurityContextHolder to TestSecurityContextHolder");
SecurityContextHolder.setContext(TestSecurityContextHolder.getContext());
});
}
}
弹簧靴
https://stackoverflow.com/questions/51622300
复制相似问题