회고/코드초보 플랫폼 독립 프로젝트
[회고] Security가 관련되어 있는 테스트 시 WithSecurityContextFactory 활용.
gracelove91
2020. 8. 8. 04:15
https://github.com/code-chobo/dev-api 프로젝트를 진행하며 쓰는 회고입니다.
문제점
- 테스트 시 현재 로그인된 사용자가 있다는 전제로 테스트를 한다면?
- 테스트 내부에서
SecurityContextHolder.context
등에UsernamePasswordAuthenticationToken
을 set 해주고.. 어쩌구 저쩌구.. 테스트가 몇 개 없다면 상관없지만, 테스트가 여러 개 있다면? 일일히 다 해줘야하나? WithSecurityContextFactory
를 이용하자.
- 테스트 내부에서
코드
WithAccountSecurityContextFactory.class
/**
* @author : Eunmo Hong
* @since : 2020/07/26
*/
@RequiredArgsConstructor
public class WithAccountSecurityContextFactory implements WithSecurityContextFactory<WithAccount> {
private final AccountService accountService;
@Override
public SecurityContext createSecurityContext(WithAccount annotation) {
String nickname = annotation.value();
String email = nickname + "@email.com";
String password = "11111111";
JoinAccountRequest joinAccountRequest = new JoinAccountRequest(email, nickname, password, password);
accountService.join(joinAccountRequest);
UserDetails userDetails = accountService.loadUserByUsername(email);
Authentication authentication = new UsernamePasswordAuthenticationToken(userDetails, userDetails.getPassword(), userDetails.getAuthorities());
SecurityContext context = SecurityContextHolder.createEmptyContext();
context.setAuthentication(authentication);
return context;
}
}
WithAccount
@Retention(RetentionPolicy.RUNTIME)
@WithSecurityContext(factory = WithAccountSecurityContextFactory.class)
public @interface WithAccount {
String value();
}
테스트
StudyApiControllerIntegrationTest
...
@DisplayName("스터디 참가 성공")
@WithAccount("joiner")
@Test
void joinStudyTest() throws Exception {
Account account = accountRepository.findByNickname("joiner").get();
CreateStudyRequest request = createStudyRequest(10, 12);
Long studyAccountId = studyService.createStudy(request, account);
StudyAccount studyAccount = studyAccountRepository.findById(studyAccountId).get();
Long studyId = studyAccount.getStudy().getId();
mockMvc.perform(post("/api/study/member")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(joinStudyRequest(studyId))))
.andDo(print())
.andExpect(status().isOk())
.andExpect(jsonPath("$.studyAccountId").exists());
}
...
- 이미
WithAccountSecurityContextFactory
에서 가입도 진행했고,SecurityCOntextHolder
에Authentication
을 set 해줬기 때문에 이와 같은 코드를 작성할 수 있다.