我正在尝试使用 SpringBoot + Spring Data Mongo + SpringMVC 运行一些集成测试
我已经简化并通用化了代码,但它应该能够通过以下测试重现该行为。
正如您从 BookRepository
界面中看到的那样,我希望用户能够只检索他拥有的书籍 (@Query("{ 'ownerName' : '?#{principal ?.username})
) 并且我正在编写一个测试来执行 POST
以保存一本书,然后验证该书是否已正确设置所有者。
出于此处问题的目的,我已将测试简化为一个 GET
,然后调用 findAll()
问题
执行任何 MockMvc
请求后,使用 ThreadLocalSecurityContextHolderStrategy#clearContext()
清除 SecurityContext
,这会导致在我执行以下操作时抛出以下异常尝试调用 repository.findAll();
java.lang.IllegalArgumentException: 身份验证对象不能为空
图书资料库.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
}
}
最佳答案
您的案例不起作用,因为 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();
}
关于java - MockMvc 在执行请求后似乎很清楚 SecurityContext (java.lang.IllegalArgumentException : Authentication object cannot be null),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51622300/