使用 JUnit5+Spring Security 测试 Spring Boot 控制器
Posted
技术标签:
【中文标题】使用 JUnit5+Spring Security 测试 Spring Boot 控制器【英文标题】:Test spring boot controllers with JUnit5+Spring Security 【发布时间】: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.
这是因为我在测试中没有 UserDetailsService bean。我该怎么办:
SecurityConfig 需要添加 3 个 bean,例如:
@MockBean 我的用户详细信息服务用户详细信息服务; @MockBean SessionAuthenticationProvider 身份验证提供者; @MockBean SessionAuthenticationFilter sessionAuthenticationFilter;
添加 SecurityConfig 的测试实现
其他的
哪种方法更好?
【问题讨论】:
【参考方案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.MyUserDetailsService' 类型的 bean。我在我的问题中写了它。当我开始集成测试时,它会尝试启动 SecurityConfig 和 SecurityConfig 需要 MyUserDetailsService 和另外 2 个 bean以上是关于使用 JUnit5+Spring Security 测试 Spring Boot 控制器的主要内容,如果未能解决你的问题,请参考以下文章
Spring Boot 集成 JUnit5,更优雅单元测试!
使用 Spring Boot 和 JUnit5 在 Intellij 中终止所有测试
我是不是需要使用 Kotlin Junit5 和 Spring Boot 将 Spring 注释复制到内部类?
在不创建上下文的情况下禁用 Spring 和 Junit5 测试