약식 DDD구조의 application 계층 테스트 코드를 작성하던 중 @SpringBootTest를 통해 테스트를 하게 되면 매번 서버를 올렸다 내리는 것이 테스트의 효율성을 저하시키는 것 같았습니다.
그래서 사용해보기로 한 것이 @DataJpaTest 입니다.
document에 나온 @DataJpaTest에 대한 설명은 이렇습니다.
Annotation for a JPA test that focuses only on JPA components.
Using this annotation will disable full auto-configuration and instead apply only configuration relevant to JPA tests.
By default, tests annotated with @DataJpaTest are transactional and roll back at the end of each test. They also use an embedded in-memory database (replacing any explicit or usually auto-configured DataSource). The @AutoConfigureTestDatabase annotation can be used to override these settings.
SQL queries are logged by default by setting the spring.jpa.show-sql property to true. This can be disabled using the showSql attribute.
If you are looking to load your full application configuration, but use an embedded database, you should consider @SpringBootTest combined with @AutoConfigureTestDatabase rather than this annotation.
When using JUnit 4, this annotation should be used in combination with @RunWith(SpringRunner.class).
대충 JPA test시 JPA components로 등록된 것만 접근해서 @SpringBootTest 처럼 full auto-configuration을 하지 않는 다는 말입니다. 추가로 @DataJpaTest 사용시 @Transactional 과 @RollBack도 지원해준다고 하는군요.
바로 본론으로 넘어가서 위와 같이 테스트코드 관련 어노테이션을 적용했을 때 아래와 같은 문제가 터졌습니다
Caused by: org.springframework.beans.BeanInstantiationException:
Failed to instantiate [com.kinderlabs.posadmin.application.mapper.StoreInfoMapper]:
Specified class is an interface
물론 상단엔 관련된 수많은 에러가 있었지만 핵심은 이것이었습니다.
@Autowired로 StoreInfoService라는 인터페이스를 DI 시켰습니다. application 계층이 아닌 다른 계층에 있는 인터페이스이기 때문에 구현체인 StoreInfoServiceImpl도 @Import로 가져왔습니다.
그런데 위와 같은 에러가 발생했습니다.
@Autowired로 주입한 StoreInfoService를 갖고오면 안 되는건가 싶어서 구현체인 StoreInfoServiceImpl을 주입하는 것으로 바꿔봤고 관련된 컴포넌트들을 다 import했습니다.
그래도 에러는 해결되지 않았습니다.
그럼 뭐가 문제일까..?
문제는 @Autowird한 인터페이스에 있는 것이 아니라 @Import로 가져온 리스트 안에 있었습니다.
간단합니다. @Import안에 StoreInfoMapper라는 인터페이스가 있는데 이것을 구현체로 바꿔줬습니다.
위와 같이 StoreInfoMapperImpl을 import했더니 해결됐습니다.
@Autowired로 주입한 것은 interface여도 상관 없습니다!!
테스트코드 작성시 @Import로 관련된 클래스들을 가져올 땐 인터페이스는 하나라도 넣지 말자!