java.lang.IllegalStateException(未找到方法):使用自定义过滤器在一次测试中多次调用 MockMvc.perform

Posted

技术标签:

【中文标题】java.lang.IllegalStateException(未找到方法):使用自定义过滤器在一次测试中多次调用 MockMvc.perform【英文标题】:java.lang.IllegalStateException(Method not found): Calling MockMvc.perform multiple time in one test with customized Filter 【发布时间】:2021-06-19 01:13:03 【问题描述】:

为了在带有 @AuthenticationPrincipal 注释的 Spring Security 受保护的 REST api 中检索 UserDetails 对象,我在 MockMvc 对象中添加了一个自定义过滤器,例如:

@ExtendWith(SpringExtension::class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class BaseSpringIntegrationTest 
    @Autowired
    private lateinit var context: WebApplicationContext

    lateinit var mockMvc: MockMvc

    val mockUser = UsernamePasswordAuthenticationToken(MyUserDetails("MOCK_USER"), "MOCK_PASSWORD",  listOf(SimpleGrantedAuthority("MOCKED_ROLE")))

    @PostConstruct
    fun init() 
        mockMvc = MockMvcBuilders
            .webAppContextSetup(context)
            .apply<DefaultMockMvcBuilder>(springSecurity(mockSpringSecurityFilter))
            .build()
    

    private val mockSpringSecurityFilter = object: Filter 
        override fun doFilter(req: ServletRequest, res: ServletResponse, chain: FilterChain) 
            with ((req as HttpServletRequest).userPrincipal) 
                if (this != null)
                    SecurityContextHolder.getContext().authentication = this as Authentication
                
            chain.doFilter(req, res)
        

        override fun destroy() 
            SecurityContextHolder.clearContext()
        
    

然后,我尝试在一些测试中调用mockMvc 对象两次,如下所示:

class DummyTests: BaseSpringIntegrationTest() 
    @Test
    fun dummyTest() 
        mockMvc.perform(MockMvcRequestBuilders.post("<MY_URL>").principal(mockUser))
            .andExpect(MockMvcResultMatchers.status().`is`(HttpStatus.OK.value()))

        mockMvc.perform(MockMvcRequestBuilders.post("<ANOTHER_URL>").principal(mockUser))
            .andExpect(MockMvcResultMatchers.status().`is`(HttpStatus.OK.value()))
    

运行测试时,java.IllegalStateException 被抛出第二个perform 喜欢:

Method not found: BaseSpringIntegrationTest$mockSpringSecurityFilter$1.getFilters(org.springframework.mock.web.MockHttpServletRequest)
java.lang.IllegalStateException: Method not found: BaseSpringIntegrationTest$mockSpringSecurityFilter$1.getFilters(org.springframework.mock.web.MockHttpServletRequest)
    at org.springframework.util.ReflectionUtils.handleReflectionException(ReflectionUtils.java:104)
    at org.springframework.test.util.ReflectionTestUtils.invokeMethod(ReflectionTestUtils.java:502)
    at org.springframework.test.util.ReflectionTestUtils.invokeMethod(ReflectionTestUtils.java:427)
    at org.springframework.security.test.web.support.WebTestUtils.findFilter(WebTestUtils.java:121)
    at org.springframework.security.test.web.support.WebTestUtils.getSecurityContextRepository(WebTestUtils.java:63)
    at org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors$SecurityContextRequestPostProcessorSupport.save(SecurityMockMvcRequestPostProcessors.java:725)
    at org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors$TestSecurityContextHolderPostProcessor.postProcessRequest(SecurityMockMvcRequestPostProcessors.java:805)
    at org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder.postProcessRequest(MockHttpServletRequestBuilder.java:831)
    at org.springframework.test.web.servlet.MockMvc.perform(MockMvc.java:173)

如果测试中只有一个perform 调用,则一切正常。

有人可以帮忙解决这个问题吗。

【问题讨论】:

【参考方案1】:

我遇到了同样的问题,我通过将以下方法添加到我的 MockSpringSecurityFilter 解决了它

public void getFilters(MockHttpServletRequest mockHttpServletRequest)

【讨论】:

非常感谢您的回复。真的行!我可以认为某处有缺陷吗?

以上是关于java.lang.IllegalStateException(未找到方法):使用自定义过滤器在一次测试中多次调用 MockMvc.perform的主要内容,如果未能解决你的问题,请参考以下文章