토비의 스프링 3.1 p.670의 내용을 진행한뒤 테스트를 돌려보면 EmbeddedDatabase 에서 에러가 발생해 테스트의 일부가 실패한다.
에러의 원인은 중복 스크립트 실행이다. (테이블이 이미 있는데 또 다시 생성 스크립트 실행)
원인을 파악하기 위해 학습테스트를 여럿 만들고 테스트 소스를 여기저기 수정해가며 파악해 봤다.
@DirtiesContext 가 문제의 원인이었다.
이 애노테이션은 빈의 DI설정을 변경할경우 다음 테스트를 실행할 때 새로운 컨텍스트를 생성케 한다
문제는, 이 애노테이션으로 생성되는 컨텍스트는 완전히 새로운 컨텍스트가 아니라는 것이다.
컨텍스트가 빈을 다시 생성할 때 내장형 데이터베이스 역시 새로운 메모리에 생성해서 돌려주어야 하는데, 이 애노테이션으로 생성된 컨텍스트는
기존에 생성됐던 내장형 데이터베이스에 다시 작업을 진행한다.
이 과정에서 이미 테이블까지 완성시킨 내장 데이터베이스에 다시 한 번 테이블 스크립트를 실행하고 SQL익셉션을 내뱉는 것이다.
왜 이렇게 작동하는지는 아직 정확한 이유를 알 수 없다.
한가지 알 수 있는것은 @DirtiesContext 는 컨텍스트를 완전히 새로 생성하는 것이 아니라는 것이다.
DI의 정보가 수정된 빈만 새로생성해서 돌려주거나 하는 특수한 작업을 하는 것으로 추측된다.
Junit 테스트는 컨텍스트 생성에 실패하고 다음 테스트에 다시 한 번 완전히 새로운 컨텍스트를 생성해 진행하게 된다.
(이 부분은 온전히 새로운 컨텍스트이기에 내장형 데이터베이스도 새로 생성되며 스크립트의 중복실행 또한 없다.)
결과적으로 @DirtiesContext 이후에 새로생성된 불완전한 컨텍스트로인해
@DirtiesContext이 붙은 테스트 바로 다음에 실행되는 테스트는 컨텍스트를 생성하는 과정에서 스크립트 중복실행으로 테스트가 실패하는 것이다.
@DirtiesContext 이 빈을 재생성할 때 어떤 작업을 하길래 이러한 문제가 발생하는지 해결 방법은 없는지
언젠가 스프링의 소스코드를 분석하게되면 찾아봐야겠다.