【问题标题】:NoClassDefFoundError - org/springframework/security/oauth2/client/registration/ClientRegistration when testingNoClassDefFoundError - org/springframework/security/oauth2/client/registration/ClientRegistration 测试时
【发布时间】:2023-02-23 04:53:25
【问题描述】:

我写了一个简单的 spring boot 应用程序,它使用 Firebase 使用 OAuth2。

这是配置

@Configuration
@EnableWebSecurity
@AllArgsConstructor
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity security) throws Exception {
        security
                .cors()
                .and()
                .csrf().disable()
                .authorizeHttpRequests()
                .anyRequest()
                .authenticated()
                .and()
                .oauth2ResourceServer()
                .jwt();

        return security.build();
    }

}

我有一个控制器,我想使用 MockMvc 进行测试

这是测试文件

@WebMvcTest(CodeController.class)
@WebAppConfiguration
@ContextConfiguration(classes = SecurityConfig.class)
public class CodeControllerTests {

    @MockBean
    private CodeExecutionService codeExecutionService;
    @MockBean
    private ProblemService problemService;

//    @MockBean
//    private ProblemRepo problemRepo;

    @MockBean
    private TestCaseValidationService validationService;
//    @MockBean
//    private ProblemRepo problemRepo;

    @Autowired
    private WebApplicationContext context;

    private MockMvc mockMvc;

    @BeforeEach
    public void setup() {
        mockMvc = MockMvcBuilders
                .webAppContextSetup(context)
                .apply(springSecurity())
                .build();
    }


    @Test

    void runTestCode() throws Exception {

        RunCodeDTO runCodeDTO = new RunCodeDTO("python", "something", "two-sum");
        Problem problem = ProblemUtils.getTwoSum();
        UserCode userCode = new UserCode(runCodeDTO.code(), runCodeDTO.language());
        userCode.mergeWithStub(problem.getCodeRunStub());

        List<TestResult> testResults = problem.getRunTestCases()
                .stream()
                .map(testCase -> new TestResult(testCase, Status.SUCCESS, ""))
                .toList();

        List<TestOutput> testOutputs = testResults
                .stream()
                .map(result -> new TestOutput(result.testCase(), new ValidationResult(Status.SUCCESS, "Test Case Passed")))
                .toList();


        when(problemService.getProblem(runCodeDTO.problemId())).thenReturn(Optional.of(problem));
        when(codeExecutionService.executeAllTestCases(problem.getRunTestCases(), userCode)).thenReturn(testResults);
        when(validationService.validateAllTestResults(testResults, problem.getOutputType(), problem.getValidationType())).thenReturn(testOutputs);

        mockMvc
                .perform(
                    MockMvcRequestBuilders.post("/code/test")
                        .contentType(MediaType.APPLICATION_JSON)
                        .content("")
                            .with(SecurityMockMvcRequestPostProcessors.oauth2Login())
                )
                .andExpect(status().isOk());

    }

}

我正在尝试使用 SecurityMockMvcRequestPostProcessors.oauth2Login() 模拟授权,但我得到了 NoClassDefFoundError - org/springframework/security/oauth2/client/registration/ClientRegistration

然而,实际的应用程序没有任何问题。这只是我收到此错误的测试

【问题讨论】:

  • 对于初学者来说,你的测试很奇怪(我会说错了)。删除 @WebAppConfiguration@ContextConfiguration。删除 WebApplicationContext 字段并放弃 setup 方法。在你的MockMvc上添加@Autowired,然后检查会发生什么。您在这里使用 Spring Boot 而不是使用它。

标签: java spring spring-boot spring-security integration-testing


【解决方案1】:

@m-denium 在他的评论中是正确的,而且您正在尝试构建客户端 Authentication 实现:OAuth2AuthenticationToken 在测试资源服务器(具有资源服务器依赖性)时。由于您的 conf 是 oauth2ResourceServer().jwt(),因此请使用 JwtAuthenticationToken 填充您的测试安全上下文。

您的测试应该不会比这更复杂:

import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.jwt;

@WebMvcTest(CodeController.class)
@Import({ SecurityConfig.class })
class CodeControllerTests {

    @MockBean
    private CodeExecutionService codeExecutionService;

    @MockBean
    private ProblemService problemService;

    @MockBean
    private TestCaseValidationService validationService;

    @Autowired
    MockMvc mockMvc;

    @Test
    void runTestCode() throws Exception {
        RunCodeDTO runCodeDTO = new RunCodeDTO("python", "something", "two-sum");
        Problem problem = ProblemUtils.getTwoSum();
        UserCode userCode = new UserCode(runCodeDTO.code(), runCodeDTO.language());
        userCode.mergeWithStub(problem.getCodeRunStub());

        List<TestResult> testResults = problem.getRunTestCases()
                .stream()
                .map(testCase -> new TestResult(testCase, Status.SUCCESS, ""))
                .toList();

        List<TestOutput> testOutputs = testResults
                .stream()
                .map(result -> new TestOutput(result.testCase(), new ValidationResult(Status.SUCCESS, "Test Case Passed")))
                .toList();
        when(problemService.getProblem(runCodeDTO.problemId())).thenReturn(Optional.of(problem));
        when(codeExecutionService.executeAllTestCases(problem.getRunTestCases(), userCode)).thenReturn(testResults);
        when(validationService.validateAllTestResults(testResults, problem.getOutputType(), problem.getValidationType())).thenReturn(testOutputs);

        mockMvc
            .perform(MockMvcRequestBuilders.post("/code/test")
                .contentType(MediaType.APPLICATION_JSON)
                .content("")
                .with(jwt()
                    .jwt(jwt -> jwt.claim(StandardClaimNames.SUB, "Tonton Pirate"))
                    .authorities(List.of(new SimpleGrantedAuthority("NICE"), new SimpleGrantedAuthority("AUTHOR")))))
            .andExpect(status().isOk());
    }
}

除了SecurityMockMvcRequestPostProcessors.jwt(),您还可以使用来自spring-addons-oauth2-test@WithMockJwtAuth以及this repo of mine 提供的资源(repo,其中还包含大量资源服务器示例,每个示例都有访问控制单元测试)

【讨论】:

    猜你喜欢
    • 2017-04-23
    • 1970-01-01
    • 1970-01-01
    • 2015-10-14
    • 2020-08-09
    • 1970-01-01
    • 2021-07-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多