《Spring Security》第八章 Spring Security 的测试支持

第八章 Spring Security 的测试支持

本章节只介绍 Spring Security 提供的测试支持,包含哪些关键的注解、如何设置Security测试环境、以及注解的作用。

在下一章节会介绍如何通过重写 @WithMockUser 来使用自定义的 UserDetails 对象。

官网上的是 Spring Security 与原始的 Spring Test 环境的集成,这里就不做赘述了,我们使用的是 SpringBoot Test 环境

一、设置测试环境

需要先引入 spring-security-test 依赖,这样就可以直接在 @SpringBootTest 中集成 Security 的测试环境,就是这么简单.

@RunWith(SpringRunner.class)
@SpringBootTest
public class DemoTest {
    // .. 一些 JUnit 单元测试方法
}

二、常用注解

单元测试要尽量做到“单元”化,只测试一个具体的功能,而不用将MVC、DAO各层都测试一遍。

因此这些注解可以帮助我们建立一个模拟的测试环境,使我们的测试代码只关注业务是否正常执行,代码是否正确。而不用考虑用户是否登陆,是否需要重新授权等问题。

1. @WithMockUser

在方法上使用一个模拟的用户,而不用真的去注册并登陆。

该注解会 Mock 一个用户名为‘user’,密码为 ’password‘,角色为 ’ROLE_USER’ 的Authentication,并将其注入到 SecurityContext 中。

@Test
@WithMockUser
public void getMessageByUser() {
    // 查询SecurityContext 上下文环境,可以取到 Mock 的模拟用户数据
    String username = ((UserDetails)SecurityContextHolder.getSecurityContext().getAuthentication().getPrincipal()).getUsername();
    // ......
}

思考:如果我们使用的是自定义的 CustomUserDetails 呢?比如扩展了 UserDetails 的属性,增加了 level 等级属性,那么将如何Mock并从上下文中获取呢? –这将会在下一节“自定义注解”中说明

2. @WithAnonymousUser

当需要用户登录,但是不需要用户的信息时,可以考虑以匿名用户的身份运行一些测试。这样会更加方便。

3. @WithUserDetails

使用自定义的 UserDetailsService 来创建身份验证的主题,但是需要用户存在。在正常业务中,可能还涉及到数据库查询,如果包含数据库查询,还需要与业务逻辑的数据库隔离等等问题。

自定义查找的用户名,以及自定义用来查找的 UserDetailsService。

@WithUserDetails(value = "customUsername", userDetailsServiceBeanName = "myUserDetailsService")

三、完整的测试案例

UserService 用户业务服务,提供一个创建用户的功能,并且在保存之前,记录当前创建人。

// 用户业务服务
@Service
public class UserService {
    // 创建用户,并且指定创建人与创建时间
    public User createUser(User user){
        // 从当前环境中取出当前主体的用户名
        String username = ((UserDetails)SecurityContextHolder.getSecurityContext().getAuthentication().getPrincipal()).getUsername();
        // 保存新建用户的创建者、创建时间
        user.setCreateUser(username);
        user.setCreateDate(new Date());
        return save(user);
    }
}

测试用户在创建时,是否设置了创建人(即@WithMockUser 是否把用户注入了SecurityContext中)。

@Runwith(SpringRunner.class)
@SpringBootTest
public class UserServiceTest {
    @Autowired
    UserService userService;

    @Test
    @WithMockUser(username = "admin", roles = {"ADMIN","USER"})
    public void test(){
        User user = userService.create(new User("张三"));
        Assertions.assertThat(user.getCreateUser()).isEqualsTo("admin");
    }
}
文章作者: koral
文章链接: http://luokaiii.github.io/2019/07/19/读书笔记/《SpringSecurity》/8.单元测试/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自