【问题标题】:Test spring boot controllers with JUnit5+Spring Security使用 JUnit5+Spring Security 测试 Spring Boot 控制器
【发布时间】:2021-02-08 13:49:59
【问题描述】:

我有一个 Spring Boot 应用程序,想为控制器编写集成测试。这是我的SecurityConfig

@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    private final MyUserDetailsService userDetailsService;
    private final SessionAuthenticationProvider authenticationProvider;
    private final SessionAuthenticationFilter sessionAuthenticationFilter;

    @Override
    public void configure(WebSecurity web) {
        //...
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
     /... 
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(authenticationProvider);
        auth.userDetailsService(userDetailsService);
    } 
}

这是我的控制器:

@RestController
public class MyController {

    //...

    @GetMapping("/test")
    public List<TestDto> getAll(){
        List<TestDto> tests= testService.findAll(authService.getLoggedUser().getId());
        return mapper.toTestDtos(tests);
    }
}

我创建了一个测试(JUnit 5):

@WebMvcTest(TestController.class)
class TestControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @MockBean(name = "mockTestService")
    private TestService testService;

    @Autowired
    private TestMapper mapper;

    @MockBean(name = "mockAuthService")
    private AuthService authService;

    private Test test;

    @BeforeEach
    void setUp() {
        User user = new Test();
        user.setId("userId");
        when(authService.getLoggedUser()).thenReturn(user);
        test = new Facility();
        test.setId("id");
        test.setName("name");
        when(testService.findAll("userId")).thenReturn(singletonList(test));
    }

    @Test
    void shouldReturnAllIpaFacilitiesForCurrentTenant() throws Exception {
        mockMvc.perform(get("/test").contentType(MediaType.APPLICATION_JSON))
                .andDo(print())
                .andExpect(status().isOk())
                .andExpect(jsonPath("$..id").value(test.getId()))
                .andExpect(jsonPath("$..timeOut").value(test.getName()));
    }
}

当我开始测试时出现异常:Consider defining a bean of type 'com.auth.MyUserDetailsService' in your configuration.

这是因为我在测试中没有 UserDetailsS​​ervice bean。我该怎么办:

  1. SecurityConfig 需要添加 3 个 bean,例如:

    @MockBean 我的用户详细信息服务用户详细信息服务; @MockBean SessionAuthenticationProvider 身份验证提供者; @MockBean SessionAuthenticationFilter sessionAuthenticationFilter;

  2. 添加 SecurityConfig 的测试实现

  3. 其他的

哪种方法更好?

【问题讨论】:

    标签: spring-boot spring-security junit5 spring-boot-test spring-security-rest


    【解决方案1】:

    为了使用 @WebMvcTest 为您的控制器端点编写测试,我将使用来自 MockMvc 和 Spring Security 的出色集成。

    确保您具有以下依赖项:

    <dependency>
      <groupId>org.springframework.security</groupId>
      <artifactId>spring-security-test</artifactId>
      <scope>test</scope>
    </dependency>
    

    接下来,您可以为您的MockMvc 请求模拟经过身份验证的用户,并设置用户名、角色等。

    要么使用注解在SecurityContext 中填充经过身份验证的用户以进行测试:

    @Test
    @WithMockUser("youruser")
    public void shouldReturnAllIpaFacilitiesForCurrentTenant() throws Exception {
       // ... 
    }
    

    或者使用SecurityMockMvcRequestPostProcessors之一:

    this.mockMvc
      .perform(
          post("/api/tasks")
            .contentType(MediaType.APPLICATION_JSON)
            .content("{\"taskTitle\": \"Learn MockMvc\"}")
            .with(csrf())
            .with(SecurityMockMvcRequestPostProcessors.user("duke"))
        )
      .andExpect(status().isCreated());
    

    您可以在此here 上找到更多信息。

    【讨论】:

    • 我无法开始我的测试,因为我遇到了一个异常:考虑在您的配置中定义一个 'com.auth.MyUserDetailsS​​ervice' 类型的 bean。我在我的问题中写了它。当我开始集成测试时,它会尝试启动 SecurityConfig 和 SecurityConfig 需要 MyUserDetailsS​​ervice 和另外 2 个 bean
    猜你喜欢
    • 2018-01-02
    • 1970-01-01
    • 1970-01-01
    • 2018-08-12
    • 1970-01-01
    • 2021-05-08
    • 2019-06-01
    • 2017-10-03
    • 1970-01-01
    相关资源
    最近更新 更多