2025. 3. 8. 22:44ㆍ개발
🧪 테스트 중 외부 요인이 필요했던 나의 경험
테스트를 작성하다 보면 가끔 외부 요인이 필요한 시점이 있다.
예를 들면, 회원 가입 기능을 테스트하려고 하는데 DB가 필요할 때처럼 말이다.
아래는 내가 직접 겪었던, 테스트 도중 외부 요인이 필요한 상황들이었다.
- DB에서 데이터를 조회하거나 추가해야 할 때
- 외부 HTTP 서버와 통신이 필요한 로직일 때
이런 외부 요인에 테스트가 의존하게 되면, 테스트 코드 작성이 진짜 귀찮아지고 실행도 어렵다.
나 같은 경우엔 결제 서비스에서 결제 기능을 테스트해야 했는데, 외부 결제 대행사에게 요청을 보내고, 결제 성공 여부를 받는 로직이 있었다.
💭 그래서 어떻게 테스트를 해야 했을까?
- 결제 요청을 보냈는데, 대행사 서버에 문제가 생겨 timeout이 나는 경우는?
- 이미 결제된 건이면? 그럼 또 결제를 해보고 테스트해야 하나?
진짜 결제를 계속 할 수도 없고... 결제 서버에 "테스트용으로 서버 꺼주세요~" 할 수도 없는 노릇이다.
그래서 필요한 게 바로 대역이다.
🧪 내가 썼던 대역 예시 - 회원가입 중복 체크
이번엔 좀 더 쉬운 예시로, 회원 가입 시 같은 ID가 존재하면 예외를 발생시키는 테스트를 만들어봤다.
📄 UserRegister.java
public class UserRegister {
private UserRepository userRepository;
public UserRegister(UserRepository userRepository) {
this.userRepository = userRepository;
}
public void register(String id, String pw, String email) {
User user = userRepository.findById(id);
if (user != null) {
throw new DuplicatedIdException();
}
userRepository.save(new User(id, pw, email));
}
}
여기까진 평범했다. 근데... 테스트를 하려면 DB랑 직접 붙어야 하더라.
🧪 UserRegisterTest.java
public class UserRegisterTest {
private UserRegister userRegister;
private UserRepository userRepository;
@BeforeEach
void setUp() {
userRepository = new UserRepositoryImpl();
userRegister = new UserRegister(userRepository);
}
@Test
@DisplayName("이미 같은 ID가 존재하면 가입 실패")
void dupIdExists() {
userRepository.save(new User(1L, "pw1", "test@naver.com")); //(1)
assertThrows(DupIdException.class, () -> {
userRegister.register(1L, "pw1", "test@naver.com"); //(2)
});
}
}
(1)에서 DB에 데이터를 넣고, (2)에서 중복 여부를 확인한다. 근데 말이야…
이렇게 하면 문제가 많다.
- ⚡ 테스트 느려짐 – DB 연결하고 쿼리 돌리는데 시간 꽤 걸림
- 🌐 외부 의존 – DB 상태나 네트워크 문제로 테스트 실패 날 수도 있음
- 🔒 테스트 간 간섭 – DB 상태가 공유돼서, 한 테스트가 다른 테스트에 영향 줄 수 있음
⚠️ 참고: 물론 실제 DB와의 상호작용이 필요한 경우도 있음! 통합 테스트에서는 진짜 DB 붙여서 테스트하는 경우도 있다.
💡 그럼 어떻게 해야 할까?
정답은 메모리로 대체한 DB 대역을 사용하는 거였다.
🧠 MemoryUserRepository.java
public class MemoryUserRepository implements UserRepository {
private Map<Long, User> users = new HashMap<>();
@Override
public void save(User user) {
users.put(user.getUserId(), user);
}
@Override
public User findById(Long id) {
return users.get(id);
}
}
DB 대신 HashMap
을 쓰는 거라 속도도 빠르고, 테스트 격리도 가능하다!
의존성 주입도 생성자로 처리해놔서 실제 DB → Memory 대역으로 바꾸는 것도 너무 쉬웠고.
🛠 왜 메모리 대역이 좋은가?
- 🚀 테스트 속도 빨라짐: 메모리는 DB보다 훨씬 빠름
- 🧼 테스트 격리 용이: 테스트 전후로 초기화도 간단
- 🧪 신뢰도 상승: 외부 요인 없이, 오직 코드만 테스트 가능
그래서 난 그 뒤로 웬만하면 테스트에는 Memory Repository 같은 대역을 적극 쓰려고 한다.
역시 테스트는 속도와 신뢰가 생명이다. 😊
'개발' 카테고리의 다른 글
[트러블 슈팅] 테스트 실행 시간이 너무 길어요! (0) | 2025.03.25 |
---|---|
배포 오류 : Asciidoctor 빌드 오류(asGemPath()) (0) | 2025.03.09 |
CI/CD : 테스트 실패시, Push 안되게 하기 (0) | 2025.03.09 |
CI/CD : Github Actions를 이용한 배포 자동화 (0) | 2025.03.09 |
테스트 범위와 종류 : 단위 테스트, 통합 테스트 (0) | 2025.03.08 |