如何为含Lambda表达式的Spring Security配置编写Mockito单元测试
如何测试返回Lambda表达式的Spring Security Bean方法
问题背景
你需要为Spring Security配置类中返回Lambda实现的authoritiesMapper() Bean编写单元测试,但现有测试无法覆盖Lambda内的代码。
原Bean方法代码
@Bean public GrantedAuthoritiesMapper authoritiesMapper() { return (authorities) -> { Set<GrantedAuthority> mappedAuthorities = new HashSet<>(); authorities.forEach(authority -> { if (OAuth2UserAuthority.class.isInstance(authority)) { OAuth2UserAuthority oauth2UserAuthority = (OAuth2UserAuthority)authority; Map<String, Object> userAttributes = oauth2UserAuthority.getAttributes(); ((List<String>) userAttributes.getOrDefault("field", List.of())).forEach(a-> mappedAuthorities.add( new SimpleGrantedAuthority(a))); } }); return mappedAuthorities; }; }
现有未覆盖代码的测试
@Before public void setUp() { this.config = new Config(); // Config类包含authoritiesMapper方法 } @Test public void testMapper(){ this.config.authoritiesMapper(); }
问题原因
你的测试仅调用了authoritiesMapper()方法获取GrantedAuthoritiesMapper实例,但Lambda表达式的逻辑只会在该实例的mapAuthorities()方法(GrantedAuthoritiesMapper接口的核心方法)被调用时执行。现有测试完全没触发这个方法,自然无法覆盖Lambda内的代码。
解决方案
直接构造测试用的权限集合,调用GrantedAuthoritiesMapper的mapAuthorities()方法,验证输出结果即可。这个场景无需Mockito,手动构造测试对象更直接。
完整测试示例
import org.junit.Before; import org.junit.Test; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.oauth2.core.user.OAuth2UserAuthority; import java.util.*; import static org.junit.Assert.*; public class ConfigTest { private Config config; private GrantedAuthoritiesMapper authoritiesMapper; @Before public void setUp() { config = new Config(); authoritiesMapper = config.authoritiesMapper(); // 获取Mapper实例 } @Test public void testAuthoritiesMapper_WithOAuth2UserAuthority() { // 1. 构造带目标属性的OAuth2UserAuthority Map<String, Object> userAttributes = new HashMap<>(); userAttributes.put("field", Arrays.asList("ROLE_USER", "ROLE_ADMIN")); OAuth2UserAuthority oauth2Authority = new OAuth2UserAuthority(userAttributes); // 2. 构造输入权限集合 Collection<? extends GrantedAuthority> inputAuthorities = Collections.singletonList(oauth2Authority); // 3. 调用mapAuthorities触发Lambda逻辑 Collection<? extends GrantedAuthority> result = authoritiesMapper.mapAuthorities(inputAuthorities); // 4. 验证结果 assertEquals(2, result.size()); assertTrue(result.contains(new SimpleGrantedAuthority("ROLE_USER"))); assertTrue(result.contains(new SimpleGrantedAuthority("ROLE_ADMIN"))); } @Test public void testAuthoritiesMapper_WithoutOAuth2UserAuthority() { // 构造普通权限,验证不会被处理 Collection<? extends GrantedAuthority> inputAuthorities = Collections.singletonList(new SimpleGrantedAuthority("ROLE_GUEST")); Collection<? extends GrantedAuthority> result = authoritiesMapper.mapAuthorities(inputAuthorities); assertTrue(result.isEmpty()); } @Test public void testAuthoritiesMapper_NoFieldAttribute() { // 构造无目标属性的OAuth2UserAuthority Map<String, Object> userAttributes = new HashMap<>(); OAuth2UserAuthority oauth2Authority = new OAuth2UserAuthority(userAttributes); Collection<? extends GrantedAuthority> inputAuthorities = Collections.singletonList(oauth2Authority); Collection<? extends GrantedAuthority> result = authoritiesMapper.mapAuthorities(inputAuthorities); assertTrue(result.isEmpty()); } }
关键要点
- 必须触发Lambda对应的接口方法:不要只调用获取Bean的方法,一定要调用
mapAuthorities()才能执行Lambda内的逻辑 - 覆盖多场景测试:包含目标属性的OAuth2权限、普通权限、无目标属性的OAuth2权限,确保所有逻辑分支都被覆盖
- 优先手动构造测试对象:这个场景无需Mockito,直接构造测试用例更简洁;若有复杂依赖再结合Mockito使用
内容的提问来源于stack exchange,提问作者XAJA
相关产品推荐
相关产品推荐

