spring - 测试 Spring 端点时如何防止 NestedServletException?

标签 spring unit-testing integration-testing mockmvc

我正在尝试 测试安全配置使用 @PreAuthorize(#oauth2.hasScope('scope') 保护的一些端点.当使用不具有所需范围的访问 token 通过 Postman 访问此类端点时,将返回以下 HTTP 状态代码 403(禁止):

{
    "error": "insufficient_scope",
    "error_description": "Insufficient scope for this resource",
    "scope": "scope"
}

这是我想要的预期行为。

在尝试测试此配置时,Springs NestedServletException在完成我的预期结果之前干扰了我的测试用例。

这是我要测试的 Controller 的简化版本:
@RestController
@RequestMapping(value = "/api")
public class OauthTestingResource {

    @PreAuthorize(#oauth2.hasScope('scope'))
    @RequestMapping(value = "/scope", method = RequestMethod.GET)
    public void endpoint() {
        // ...
    }
}

这是相应的测试用例:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = MyApplication.class)
@WebAppConfiguration
public class AuthorizationTest {

    @Autowired
    protected WebApplicationContext webApplicationContext;

    protected SecurityContext securityContext = Mockito.mock(SecurityContext.class);

    @Before
    public void setup() throws Exception {

        this.mvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
        SecurityContextHolder.setContext(securityContext);
    }

    protected Authentication createMockAuth(Client client) {

        final List<GrantedAuthority> authorities = new ArrayList<>();
        authorities.add(new SimpleGrantedAuthority("ROLE_USER"));

        final Authentication pwAuth = new UsernamePasswordAuthenticationToken("testuser", "testpw", authorities);

        final TokenRequest request = new TokenRequest(new HashMap<>(), client.getClientId(), client.getScopes(), "password");

        final OAuthClient oauthClient = new OAuthClient(client, GrantType.PASSWORD);

        return new OAuth2Authentication(request.createOAuth2Request(oauthClient), pwAuth);
    }
    @Test
    public void testAppScope() throws Exception {

        final Client client = new Client("id1", "secret1");

        client.setScope("scope");
        Mockito.when(securityContext.getAuthentication()).thenReturn(createMockAuth(client));
        // this test passes
        mvc.perform(get("/api/scope")).andExpect(status().isOk()); 

        client.setScope("other_scope");
        Mockito.when(securityContext.getAuthentication()).thenReturn(createMockAuth(client));
        // NestedServletException thrown here
        mvc.perform(get("/api/scope")).andExpect(status().isForbidden()); 
    }
}

引发的异常如下(这是预期的):

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.security.access.AccessDeniedException: Insufficient scope for this resource



我的问题是如何防止此异常干扰我的测试用例?

最佳答案

我有一个类似的情况,并通过使用抑制了 NestedServletException@Test(expected = NestedServletException.class)然后我能够掌握 MvcResult 并对其进行进一步的断言,就像在其他测试中一样:

// then
MvcResult result = resultActions.andExpect(status().isServiceUnavailable()).andReturn();
String message = result.getResponse().getContentAsString();
assertThat(message).contains("ABC");
assertThat(result.getResolvedException().getClass()).isEqualTo(XYZ.class);
它似乎奏效了。

关于spring - 测试 Spring 端点时如何防止 NestedServletException?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44900646/

相关文章:

jakarta-ee - Java EE/JPA 集成测试和 Spring 一样的回滚

c# - 如何在流畅的断言中比较 null 和 string.Empty (或 "")?

java - 通过Java Config更改Springboot Actuator服务管理端口

java - 如何处理应用 BeanValidation 关系约束的错误?

java - Spring RMI刷新StubOnConnectFailure不工作

java - 如何在生成之后但测试执行之前修改数据库模式?

java - 如何在 Spring 中获取单例 Controller 的原型(prototype) bean?

unit-testing - 如何测试Gulp任务

java - 模拟子类对象和父类(super class)引用

ruby-on-rails - 您如何在不对ActiveRecord::Base方法进行使用做任何假设的情况下对它们进行 stub ?