현재 인증 및 인가를 아래 코드와 같이 @PreAuthorize 애너테이션을 이용해서 진행하고 있습니다.
// MeberCommandServiceImpl.class
// Member Profile Update 하는 메서드
@Override
@PreAuthorize("isAuthenticated() and hasAuthority('MEMBER') and authentication.principal.username == #authUsername")
public void update(String authUsername, ModifyRequest modifyRequest) {
Member validMember = memberQueryService.getMemberByUsername(authUsername);
if (memberQueryService.isNicknameDuplicate(modifyRequest.nickname()).isExist()) {
throw new CustomException(CustomResponseStatus.NICKNAME_ALREADY_EXIST);
}
validMember.update(modifyRequest);
}
@Profile("test")
@ExtendWith(MockitoExtension.class)
@EnableMethodSecurity
class MemberCommandServiceImplTest {
@Mock
private MemberRepository memberRepository;
@Mock
private MemberQueryService memberQueryService;
@Mock
private PasswordEncoder passwordEncoder;
@InjectMocks
private MemberCommandServiceImpl commandService;
@Test
@DisplayName("본인이 아닌 경우 프로필 수정 실패")
@WithMockUser(username = "[email protected]", authorities = {"MEMBER"})
void profileUpdateFailNotAuthorize() throws Exception {
// given
Member member = createMember();
String authUsername = "[email protected]";
ModifyRequest validModifyRequest = new ModifyRequest("newNickname", "newProfile.jpeg");
when(memberQueryService.getMemberByUsername(anyString())).thenReturn(member);
when(memberQueryService.isNicknameDuplicate(anyString())).thenReturn(new ExistResponse(false));
// then, when
assertThatThrownBy(() -> commandService.update(authUsername, validModifyRequest))
.isInstanceOf(AccessDeniedException.class)
.hasMessage("Access Denied");
}
}
해당 메서드의 인증, 인가 실패에 대한 테스트코드를 다음과 같이 작성해보았다.
그리고 실행해보면
java.lang.AssertionError:
Expecting code to raise a throwable.
at com.kaboot.community.domain.member.service.member.impl.MemberCommandServiceImplTest.profileUpdateFailNotAuthorize(MemberCommandServiceImplTest.java:113)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
위와 같은 에러가 발생하는데, throw를 기대했지만 발생하지 않았다는 오류가 발생한다.
서비스 로직에서는 메서드의 로직이 실행되기 전 @PreAuthorize를 통해 인증 및 인가가 진행되어야 하며, 인증과정 실패시 에러를 뱉고있다.
하지만, 테스트 코드에서는 이러한 인증 및 인가 로직이 적용되지 않고 메서드 실행만 되고있을 뿐이다.
왜 이런 문제가 발생했을까?
@PreAuthorize의 경우 Spring Security에서 제공하는 인증, 인가 애너테이션입니다만
현재 테스트코드의 경우 단위테스트인 만큼 최대한 가볍게 테스트 하기 위해 테스트에 필요한 최소한의 객체를 @Mock과 @InjectMocks를 이용해서 Mocking하는 방식을 선택하고 있습니다.