今天群里新人疑惑的问我:大哥,SpringSecurity让我无法运行单元测试,总是401,你看怎么解决。没问题,如果你有写单元测试的意识,你写的代码质量一定要有保证,一定要注意代码质量。这种帮助一定要帮!SpringSecurity测试环境要在单元测试中使用SpringSecurity,需要在Boot项目中的SpringIntegration中:org.springframework.securityspring-security-testtest这样测试的context配置就是可以和SpringSecurity结合,接下来教大家几招。所有SpringSecurity测试都在SpringBootTest下执行,这是由@SpringBootTest注释支持的。@WithMockUser@WithMockUser注解可以帮助我们在SpringSecurity安全上下文中模拟一个默认名为user,默认密码为password,默认角色为USER的用户。当你的测试方法使用这个注解时,你可以通过:Authenticationauthentication=SecurityContextHolder.getContext().getAuthentication();获取模拟用户的信息,“假装”该用户用户当前已登录。当然你也可以根据需要自定义用户名、密码、角色:@SneakyThrows@Test@WithMockUser(username="felord",password="felord.cn",roles={"ADMIN"})voidupdatePassword(){模拟Mvc。perform(post("/user/update/password").contentType(MediaType.APPLICATION_JSON).content("{\n"+"\"newPassword\":\"12345\",\n"+"\"oldPassword\":\"12345\"\n"+"}")).andExpect(ResultMatcher.matchAll(status().isOk())).andDo(print());}当然你可以标记@WithMockUser在整个测试类上,以便每个测试都将使用指定的用户。@WithAnonymousUser@WithAnonymousUser用于模拟特殊用户,也称为匿名用户。如果需要测试匿名用户,可以直接使用这个注解。其实相当于@WithMockUser(roles={"ANONYMOUS"})和@WithMockUser(authorities={"ROLE_ANONYMOUS"})。如果你仔细的话,你应该能够看到差异。@WithUserDetails虽然@WithMockUser是一种非常方便的方法,但它可能并非在所有情况下都有效。有时你会神奇地改变一些东西来改变安全上下文的验证机制。比如自定义UserDetails,这种注解就不好用了。但是通过UserDetailsS??ervice加载的用户往往是可靠的。所以@WithUserDetails派上用场了。@SneakyThrows@Test@WithUserDetails("felord")voidupdatePassword(){mockMvc.perform(post("/user/update/password").contentType(MediaType.APPLICATION_JSON).content("{\n"+"\"newPassword\":\"12345\",\n"+"\"旧密码\":\"12345\"\n"+"}")).andExpect(ResultMatcher.matchAll(status().isOk())).andDo(print());}当我们执行单元测试时,会通过UserDetailsS??ervice的loadUserByUsername方法找到名为felord的用户,并加载到安全上下文中。自定义注解其实我们也可以模拟@WithMockUser@Target({ElementType.METHOD,ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Inherited@Documented@WithSecurityContext(factory=WithMockUserSecurityContextFactory.class)public@interfaceWithMockUser{Stringvalue()默认"用户";Stringusername()默认"";String[]roles()default{"USER"};String[]authorities()default{};Stringpassword()默认"密码";@AliasFor(annotation=WithSecurityContext.class)TestExecutionEventsetupBefore()defaultTestExecutionEvent.TEST_METHOD;}关键在于@WithSecurityContext注解,我们只需要实现工厂即可,即:publicinterfaceWithSecurityContextFactory{SecurityContextcreateSecurityContext(Aannotation);}这里,按照同样的方法,而且演示没有难度。小结今天我介绍了如何在你的应用中集成SpringSecurity时进行单元测试。我们可以使用提供的注解来模拟用户,或者模拟加载用户,你甚至可以根据自己的需要进行自定义。其实如果用JWT,还是有野路子的。可以在SpringMVCMock测试中添加相应的请求头或参数,就可以顺利进行。