기능 구현은 완료했으니, 테스트 코드를 작성하자
LockAopAspectTest
package com.example.account.service;
import com.example.account.dto.UseBalance;
import com.example.account.exception.AccountException;
import com.example.account.type.ErrorCode;
import org.aspectj.lang.ProceedingJoinPoint;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@ExtendWith(MockitoExtension.class)
class LockAopAspectTest {
@Mock
private LockService lockService;
@Mock
private ProceedingJoinPoint proceedingJoinPoint;
@InjectMocks
private LockAopAspect lockAopAspect;
@Test
@DisplayName("Lock과 unLock이 잘 수행되는가")
void lockAndUnlock() throws Throwable {
//given
// 계좌를 확인하기 위해서는 argumentCaptor를 사용한다.
ArgumentCaptor<String> lockArgumentCaptor = ArgumentCaptor.forClass(String.class);
ArgumentCaptor<String> unlockArgumentCaptor = ArgumentCaptor.forClass(String.class);
UseBalance.Request request = new UseBalance.Request(1L,"1000000000",1000L);
//when
lockAopAspect.aroundMethod(proceedingJoinPoint, request);
//then
verify(lockService, times(1)).lock(lockArgumentCaptor.capture());
verify(lockService, times(1)).unlock(unlockArgumentCaptor.capture());
assertEquals("1000000000", lockArgumentCaptor.getValue());
assertEquals("1000000000", unlockArgumentCaptor.getValue());
}
@Test
@DisplayName("excepiton이 발생하더라도 Lock과 unLock이 잘 수행되는가")
void lockAndUnlock_evenIfThrow() throws Throwable {
//given
// 계좌를 확인하기 위해서는 argumentCaptor를 사용한다.
ArgumentCaptor<String> lockArgumentCaptor = ArgumentCaptor.forClass(String.class);
ArgumentCaptor<String> unlockArgumentCaptor = ArgumentCaptor.forClass(String.class);
UseBalance.Request request = new UseBalance.Request(1L,"1000000000",1000L);
given(proceedingJoinPoint.proceed()) // 에러 던져주기
.willThrow(new AccountException(ErrorCode.ACCOUNT_NOT_FOUND));
//when
assertThrows(AccountException.class, () -> lockAopAspect.aroundMethod(proceedingJoinPoint, request));
//then
verify(lockService, times(1)).lock(lockArgumentCaptor.capture());
verify(lockService, times(1)).unlock(unlockArgumentCaptor.capture());
assertEquals("1000000000", lockArgumentCaptor.getValue());
assertEquals("1000000000", unlockArgumentCaptor.getValue());
}
}
LockServiceTest
package com.example.account.service;
import com.example.account.exception.AccountException;
import com.example.account.type.ErrorCode;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.BDDMockito.given;
@ExtendWith(MockitoExtension.class)
class LockServiceTest {
@Mock
private RedissonClient redissonClient;
@Mock
private RLock rLock;
@InjectMocks
private LockService lockService;
@Test
@DisplayName("Lock 취득 성공")
void successGetLock() throws Exception{
//given
given(redissonClient.getLock(anyString()))
.willReturn(rLock);
given(rLock.tryLock(anyLong(), anyLong(), any()))
.willReturn(true);
//when
assertDoesNotThrow(() -> lockService.lock("123")); // lock을 취득하면 아무런 오류 발생 x
}
@Test
@DisplayName("Lock 취득 실패")
void failGetLock() throws Exception{
//given
given(redissonClient.getLock(anyString()))
.willReturn(rLock);
given(rLock.tryLock(anyLong(),anyLong(),any()))
.willReturn(false);
//when
AccountException exception = assertThrows(AccountException.class, () -> lockService.lock("123"));
//then
assertEquals(exception.getErrorCode(), ErrorCode.ACCOUNT_TRANSACTION_LOCK);
}
}
'Project' 카테고리의 다른 글
[Weather Diary] JDBC 방식으로 데이터 저장 (0) | 2023.09.01 |
---|---|
[Toss] 리팩토링 (0) | 2023.08.30 |
[Toss] 중복거래 방지 기능 (0) | 2023.08.29 |
[Toss] 예외처리 수정 (0) | 2023.08.28 |
[Toss] 잔액사용 확인(2) (0) | 2023.08.26 |