Spring 프레임워크 기반으로 서비스를 개발할 때 간혹 단위 테스트하기 어려운 경우를 마주합니다.
저는 S3 리소스 연동 모듈을 사용하여 서비스를 개발한 적이 있는데 테스트 코드를 작성할 때 서비스 클래스가 S3와 강한 의존성을 갖고 있어 테스트하기 어려웠던 경험이 있습니다. 리소스를 효율적으로 사용하기 위해서 반드시 연동을 테스트해야 하는 경우가 아니라면 임시 모듈로 교체할 필요가 있습니다.
밑에 샘플 코드를 통해 비슷한 예시를 들 수 있습니다.
샘플 코드
@Service
public class GithubService {
public RepositoryInformation getInformation(String owner, String repositoryName) throws IOException {
// 특정 모듈에 대한 의존성이 높아 서비스(단위) 테스트가 어려워지게 됩니다.
GitHub github = GitHub.connect();
GHRepository repository = github.getRepository(...);
return new RepositoryInformation(...);
}
}
문제
서비스 코드의 로직을 테스트할 때 Github.connect()와 같이 서비스 코드에서 직접 구현체를 받아오면 테스트하기 어려운 경우가 발생합니다. Github 클래스의 정적 메서드인 connect()의 리턴값에 의존적이기 때문이죠.
개선
직접 서비스 코드에서 Github.connect()를 통해 Github 인스턴스를 받아오지 않고 필요한 메서드를 가진 인터페이스를 정의하고 구현체를 정의해서 사용하면 어떨까요?
public interface GithubConnector {
GitHub connect() throws IOException;
}
public class AnonymousGithubConnector implements GithubConnector {
@Override
public GitHub connect() throws IOException {
return GitHub.connectAnonymously();
}
}
샘플 테스트 코드를 보여드리면 좋겠지만 간단하게 예시를 들기 때문에 Config 클래스에서 간단하게 의존성을 주입해보곘습니다.
@Configuration
public class GithubConfig {
@Bean
public GithubConnector githubConnector() {
return new AnonymousGithubConnector();
}
}
GithubService 클래스에서 의존성을 주입받도록 코드를 개선할 수 있습니다.
@Service
public class GithubService {
private GithubConnector githubConnector;
public GithubService(GithubConnector githubConnector) {
this.githubConnector = githubConnector;
}
public RepositoryInformation getInformation(String owner, String repositoryName) throws IOException {
GitHub github = githubConnector.connect();
GHRepository repository = github.getRepository(owner + "/" + repositoryName);
return new RepositoryInformation(repository.getFullName(), repository.getStargazersCount(), repository.getForksCount());
}
}
추상화를 통해 사용자 클래스를 정의해서 갈아 끼워 줄 수 있도록 유연해지고 테스트하기도 전에 비해 훨씬 수월해졌습니다.
관련해서 더 자세한 내용은 Portable Service Abstraction (PSA) 키워드로 찾아보시면 도움이 될 겁니다.
'개발 > Spring Framework' 카테고리의 다른 글
[Spring Data JPA] saveAll은 만능일까? (1) | 2023.02.15 |
---|---|
TestContainers가 Docker 감지 못 하는 문제 (Mac) (1) | 2023.01.05 |
IoC(제어의 역전), DI(의존관계 주입), Container(컨테이너) (0) | 2022.06.05 |