【发布时间】:2018-12-15 22:44:01
【问题描述】:
我正在使用 Junit 5 测试 Web 应用程序,除了
SecurityContextHolder.getContext().getAuthentication().getPrincipal()
在运行测试用例时控制器类中的线
的线返回对象代码org.springframework.security.core.userdetails.User 而不是 MyUserDetails (而在 Spring Boot 中运行的应用程序返回对象是 MyUserDetails 并且代码运行良好)
我的测试用例类
@ExtendWith(SpringExtension.class)
@WebMvcTest(VendorController.class)
@AutoConfigureMockMvc
class VendorControllerTest {
@Autowired
private MockMvc mvc;
@Test
void test() throws Exception {
mvc.perform(MockMvcRequestBuilders.post("/vendor/user/getVendorList").with(csrf().asHeader())
.param("iDisplayStart","0")
.param("iDisplayLength", "10")
.param("iSortCol_0", "0")
.param("sSortDir_0", "asc")
.param("sSearch","")
.with(user("username").password("password").roles("2"))).andExpect(status().isOk());
}
}
我缺少什么代码,以便在使用 Junit 5 运行测试用例时返回 org.springframework.security.core.userdetails.User 对象,但如果我通过 Spring Boot 运行项目,则可以正常工作。
添加 UserDetailsService 实现代码
@Service("userDetailsService")
public class MyUserDetailsService implements UserDetailsService {
@Autowired
private UserSvc userSvc;
@Transactional(readOnly=true)
@Override
public UserDetails loadUserByUsername(final String username) throws UsernameNotFoundException {
com.esociety.entity.UserEntity userEntity = userSvc.findByUserName(username);
List<GrantedAuthority> authorities = buildUserAuthority(userEntity.getUserType());
return buildUserForAuthentication(userEntity, authorities);
}
private User buildUserForAuthentication(com.esociety.entity.UserEntity userEntity, List<GrantedAuthority> authorities) {
MyUserDetails myUserDetails = new MyUserDetails (userEntity.getUsername(), userEntity.getPassword(), userEntity.isEnabled(), userEntity.isAccountNonExpired(), userEntity.isCredentialsNonExpired(),userEntity.isAccountNonLocked(),authorities,userEntity.getUserId(),userEntity.getSocietyId(),userEntity.getUserType(),userEntity.getFirstName(),userEntity.getMiddleName(),userEntity.getLastName());
return myUserDetails;
}
private List<GrantedAuthority> buildUserAuthority(String userType) {
Set<GrantedAuthority> setAuths = new HashSet<GrantedAuthority>();
// Build user's authorities
setAuths.add(new SimpleGrantedAuthority(userType));
List<GrantedAuthority> Result = new ArrayList<GrantedAuthority>(setAuths);
return Result;
}
}
MyUserDetails 类
public class MyUserDetails extends User {
public MyUserDetails(String username, String password, boolean enabled,
boolean accountNonExpired, boolean credentialsNonExpired,
boolean accountNonLocked,
Collection<? extends GrantedAuthority> authorities, Long userId,
Long societyId, String userType, String firstName,
String middleName, String lastName) {
super(username, password, enabled, accountNonExpired,
credentialsNonExpired, accountNonLocked, authorities);
this.userId = userId;
this.societyId = societyId;
this.userType = userType;
this.firstName = firstName;
this.middleName = middleName;
this.lastName = lastName;
}
// getter setter goes here
}
【问题讨论】:
-
您是否使用
UserDetailsService的实现来返回MyUserDetails?如果是这样,您如何使该服务可用于测试(因为您没有加载整个 SpringApplication 上下文)? -
@AndreiDamian-Fekete 我添加了 userDetailsService 实现代码。当我登录应用程序时,会调用 buildUserForAuthentication 方法并创建一个扩展 User 的 MyUserDetails 对象,但我相信如果在 Junit 测试时应该调用 buildUserForAuthentication 方法,那么我将不会遇到类转换异常问题。
标签: spring-mvc spring-boot junit spring-security junit5