I made a test Using @WithMockCustomUser annotation. Since My Service Logic needs User's email, I needed to make CustomSecurirtyContextFactory. So I made it and Use it in WithMockCustomUser
What I'm wondering is that why should I need default value in WithMockCustomUser?
I've already set values in CustomUserDetails in WithMockCustomUserSecurityContextFactory.. I've checked values and find out that default values are not used.. Test is using values in CustomUserDetails so those default values looks meaningless to me.
Let me show you my code
Service I'm trying to test
public class CommentService {
private final CommentRepository commentRepository;
private final PostsRepository postsRepository;
private final UserDetailService userDetailService;
@Transactional
public Long commentSave(CommentSaveRequestDto requestDto, Long id) {
Posts post = postsRepository.findById(id)
.orElseThrow(() -> new IllegalArgumentException("해당 게시글이 존재하지 않습니다"));
requestDto.setPosts(post);
User user = userDetailService.returnUser();
requestDto.setUser(user);
return commentRepository.save(requestDto.toEntity()).getId();
}
UserDetailService used In above service
@RequiredArgsConstructor
@Service
public class UserDetailService implements UserDetailsService {
private final UserRepository userRepository;
public User returnUser() {
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
String userName;
if (principal instanceof UserDetails) {
userName = ((UserDetails) principal).getUsername();
} else {
userName = principal.toString();
}
System.out.println("유저 : " + userName);
int start = userName.indexOf("email")+6;
int end = userName.indexOf(".com,")+4;
String email = userName.substring(start, end);
System.out.println("이메일 : " + email);
User user = userRepository.findByEmail(email).orElse(null);
return user;
}
public Principal returnPrincipal() {
return (Principal) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
return (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
}
}
WithMockCustomUser
@Retention(RetentionPolicy.RUNTIME)
@WithSecurityContext(factory = WithMockCustomUserSecurityContextFactory.class, setupBefore = TestExecutionEvent.TEST_EXECUTION)
public @interface WithMockCustomUser {
String name() default "testName";
String email() default "testEmail@naver.com";
Role role() default Role.USER;
}
WithMockCustomUserSecurityContextFactory used with WithMockCustomUser
class WithMockCustomUserSecurityContextFactory implements WithSecurityContextFactory<CommentsApiControllerTest.WithMockCustomUser> {
@Override
public SecurityContext createSecurityContext(CommentsApiControllerTest.WithMockCustomUser customUser) {
SecurityContext context = SecurityContextHolder.createEmptyContext();
CustomUserDetails principal = new CustomUserDetails();
Authentication auth =
new UsernamePasswordAuthenticationToken(principal, "password", principal.getAuthorities());
context.setAuthentication(auth);
return context;
}
}
CustomUserDetails used in WithMockCustomUserSecurityContextFactory above
@Getter
class CustomUserDetails implements UserDetails {
public String name = "ㅇㅇ";
public String email = "1park5@naver.com";
public String role = Role.USER.toString();
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
ArrayList<GrantedAuthority> auth = new ArrayList<GrantedAuthority>();
auth.add(new SimpleGrantedAuthority((role)));
return auth;
}
@Override
public String getPassword() {
return null;
}
@Override
public String getUsername() {
return "email="+email+",";
}
@Override
public boolean isAccountNonExpired() {
return false;
}
@Override
public boolean isAccountNonLocked() {
return false;
}
@Override
public boolean isCredentialsNonExpired() {
return false;
}
@Override
public boolean isEnabled() {
return false;
}
}
Test Code
@Test
@WithMockCustomUser
@Transactional // 프록시 객체에 실제 데이터를 불러올 수 있게 영속성 컨텍스트에서 관리
public void comment_등록() throws Exception {
// given
String title = "title";
String content = "content";
User user = userRepository.save(User.builder()
.name("name")
.email("fake@naver.com")
.picture("fakePic.com")
.role(Role.USER)
.build());
PostsSaveRequestDto requestDto = PostsSaveRequestDto.builder()
.title(title)
.content(content)
.user(user)
.build();
postsRepository.save(requestDto.toEntity());
String comment = "comment";
Posts posts = postsRepository.findAll().get(0);
CommentSaveRequestDto saveRequestDto = CommentSaveRequestDto.builder()
.comment(comment)
.posts(posts)
.build();
Long id = posts.getId();
String url = "http://localhost:"+ port + "/api/posts/" + id + "/comments";
//when
mvc.perform(post(url)
.contentType(MediaType.APPLICATION_JSON_UTF8)
.content(objectMapper.writeValueAsString(saveRequestDto)))
.andDo(print())
.andExpect(status().isOk());
}
This doc helped me made this test
At least this test is successfully passed, I'm not Sure I made it correctly. Any comments would be very helpful. Thank you in advance.