테스트 격리란 무엇인가?
●테스트 격리란 무엇인가?
테스트 격리(Test Isolation) 는 각 테스트가 서로 독립적으로 실행되도록 보장하는 것을 말하며, 어떤 테스트가 실행되더라도 다른 테스트의 결과나 상태에 영향을 주거나 받지 않아야 한다는 의미
테스트 격리가 중요한 이유는 격리가 제대로 이루어지지 않으면 비결정적 테스트가 발생할 수 있기 때문이며 비결정적(Non-deterministic) 테스트는 같은 테스트를 여러 번 실행했을 때 항상 같은 결과를 내지 않는 테스트를 말하며 예를 들어, 테스트가 데이터베이스와 같은 공유 자원에 의존할 경우 실행 순서나 다른 테스트의 실행 여부에 따라 성공 또는 실패 결과가 달라질 수 있으며 비결정적 테스트는 실패했을 때 실제 코드의 문제인지, 비결정적 요인 때문인지 판단하기 어려워지며 따라서 테스트가 항상 동일한 조건에서 예측 가능한 결과를 낼 수 있도록 격리하는 것이 중요
●Spring에서 같은 데이터베이스를 사용하는 테스트는 어떻게 격리할 수 있을까?
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
@SpringBootTest
class MyIntegrationTest {
// ...
}
@Sql("/truncate.sql")
@SpringBootTest
class MyIntegrationTest {
// ...
}
@Transactional
@SpringBootTest
class MyIntegrationTest {
// ...
}
1.의도치 않은 트랜잭션 적용으로 프로덕션 환경과 다른 조건에서 테스트될 수 있으며 예를 들면, OSIV를 꺼두고 @Transactional도 없는 상태에서 지연로딩된 엔티티를 조회하면 LazyInitializationException이 발생하지만, 테스트에서는 트랜잭션이 열려 있어서 예외가 발생하지 않지만 실제로는 실패할 코드가 테스트에서는 성공하는 거짓 음성이 나타날 수 있음
거짓 양성(False Positive): 프로덕션 코드는 정상 동작하지만 테스트는 실패
거짓 음성(False Negative): 프로덕션 코드는 실패하지만 테스트는 통과
2.@SpringBootTest의 WebEnvironment가 DEFINE_PORT 또는 RANDOM_PORT일 경우, 별도의 스레드에서 서블릿 컨테이너가 실행되기 때문에 테스트의 트랜잭션 롤백이 적용되지 않음
3.프로덕션 코드의 트랜잭션 전파 레벨을 REQUIRES_NEW로 설정했을 경우 새로운 트랜잭션을 생성하기 때문에 테스트 트랜잭션과 무관하여 롤백되지 않음
4.비동기 메서드는 새로운 스레드에서 실행되기 때문에 롤백되지 않음