使用 JUnit 测试依赖于 Spring 安全性的 Spring 控制器



我有一个Spring应用程序,我正在构建JUnit测试来测试某个Controller

问题是在Controller中我调用此代码:

final Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
final String userName = authentication.getName();

换句话说,我需要在调用此Controller之前进行身份验证。我用这段代码写了一个JUnit测试:

private MockMvc mockMvc;
    @Test
    public void getPageTest() throws Exception{
        final ProcessFileController controller = new ProcessFileController();
        mockMvc = standaloneSetup(controller).build();
    mockMvc.perform(get(URI.create("/processFile.html")).sessionAttr("freeTrialEmailAddress", "")).andExpect(view().name("processFile"));
        }

当我运行时,它会在final String userName = authentication.getName();上给我一个NullPointerException,因为我没有登录,所以我的authentication null

问题是:有没有办法模拟身份验证?欢迎所有想法。

谢谢。

Spring Security 版本 4 对此进行了一些巧妙的改进。

首先确保在用于测试的类路径中具有测试框架,使用 Maven 时它看起来像:

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

有用的导入:

import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.*;
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.*;

测试设置:

mockMvc = webAppContextSetup(applicationContext).apply(springSecurity()).build();

(我认为你需要WebApplicationContext而不是单个控制器。

然后测试类似:

mockMvc.perform(get(...).with(user("username").roles("USER"))).andExpect(...);

理想情况下,您将使用@AuthenticationPrincipal但如果这不是一个选项,则需要使用Authentication实例设置SecurityContext,该实例将在测试中可用。

您可以在帮助程序类中使用静态方法来执行此操作。

public static void setupSecurityContext(String username, String password, String... groups)
{
  List<GrantedAuthority> authorities = new ArrayList<>();
  for (String group : groups)
  {
    authorities.add(new SimpleGrantedAuthority(group));
  }
  UserDetails user = new UserDetails(username, password, authorities);
  UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(user, password);
  SecurityContextHolder.getContext().setAuthentication(token);
}

然后在测试中,您可以简单地调用

SecurityHelper.setupSecurityContext("user", "password", "g1", "g2");

最新更新