如何测试受保护的 Spring 控制器

How to test a Spring Controller that is secured

我目前有一个使用 Spring Boot 2、Spring MVC、Spring Data/JPA 和 Thymeleaf 构建的应用程序。

我正在编写一些 unit/integration 测试,我想测试控制器,它由 Spring 由注册用户数据库支持的安全性保护。

最好的测试方法是什么?我尝试了其中一些失败,例如使用 @WithMockUser.

之类的注释

编辑:提醒一下,我不是在测试 @RestControllers。我直接在我的测试 class 上注入 @Controller 并调用它的方法。它在没有 Spring 安全性的情况下工作得很好。

一个例子:

@Controller
public class SecuredController {
  @GetMapping("/")
  public String index() {
    return "index";
  }
}

/ 路径受 Spring 安全保护,通常会重定向到 /login 以验证用户。

我的单元测试应该是这样的:

@WebMvcTest(controllers = SecuredController.class)
class SecuredControllerTest {

  @Autowired
  private SecuredController controller;

  @Autowired
  private MockMvc mockMvc;

  @Test
  @WithMockUser(username = "user", password = "pass", roles = {"USER"})
  public void testAuthenticatedIndex() throws Exception {
    mockMvc.perform(get("/"))
        .andExpect(status().isOk())
        .andDo(print());
  }
}

我得到的第一个错误是要求我注入我的 UserDetailsS​​ervice 实现,这是我想避免的事情。但是,如果我确实注入了该服务,则测试有效,但是 returns 404 而不是 200.

有什么想法吗?

在测试中class,使用注释

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)

在设置测试方法中

@Before

实测方法

@WithMockUser("spring")
@Test

像这些例子一样测试Spring安全性

https://spring.io/blog/2014/05/23/preview-spring-security-test-web-security

https://www.baeldung.com/spring-security-integration-tests

您需要通过导入 WebSecurityConfigurerAdapter class.

将您的安全配置添加到 Spring 上下文
@WebMvcTest(controllers = SecuredController.class)
@Import(SecuredControllerTest.Config.class)
class SecuredControllerTest {

   @Configuration
   @EnableWebSecurity
   static class Config extends MyWebSecurityConfigurerAdapter {
      @Autowired
      public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
          auth.inMemoryAuthentication().withUser("user").password("pa$$").roles("USER");
          auth.inMemoryAuthentication().withUser("admin").password("pa$$").roles("ADMIN");
      }
   }

   ...
}

嵌入的 static class Config 只是为了改变我们从哪里获取用户,在这种情况下 inMemoryAuthentication 就足够了。