You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
로컬에서 사용하는 애플리케이션 서버와 테스트에서 같은 데이터베이스를 사용하면 테스트 문제가 발생
이런 문제를 해결하려면 테스트를 다른 환경과 분리해야 함
가장 간단한 방법 테스트 전용 데이터베이스를 별도로 운영하는 것
1. jdbc:h2:tcp://localhost//test local에서 접근하는 서버 전용 데이터베이스
2. jdbc:h2:tcp://localhost//testcase test 케이스에서 사용하는 전용 데이터베이스
테이블 생성하기
testcase 데이터베이스에도 item 테이블 생성
main-application.properties
test-application.properties
테스트 중요 원칙
테스트는 다른 테스트와 격리
테스트는 반복해서 실행할 수 있어야 함
테스트 - 데이터 롤백
트랜잭션과 롤백 전략
이때 도움이 되는 것은 트랜잭션
테스트가 끝나고 나서 트랜잭션을 강제로 롤백해버림, 데이터가 제거 됨
테스트를 하면서 데이터를 이미 저장했는데, 중간에 테스트가 실패해서 롤백을 호출하지 않아도 됨, 트랜잭션을 커밋하지 않아 디비에 해당 데이터가 반영되지 않음
트랜잭션 시작 -> 테스트 A 실행 -> 트랜잭션 롤백 -> 트랜잭션 시작 -> 테스트 B 실행 -> 트랜잭션 롤백
packagehello.itemservice.domain;
importhello.itemservice.repository.ItemRepository;
importhello.itemservice.repository.memory.MemoryItemRepository;
importorg.junit.jupiter.api.AfterEach;
importorg.junit.jupiter.api.BeforeEach;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.boot.test.context.SpringBootTest;
importorg.springframework.transaction.PlatformTransactionManager;
importorg.springframework.transaction.TransactionStatus;
importorg.springframework.transaction.support.DefaultTransactionDefinition;
@SpringBootTestclassItemRepositoryTest2 {
@AutowiredItemRepositoryitemRepository;
//트랜잭션 관련 코드//트랜잭션 관리자는 PlatformTransactionManager 주입 받아서 사용, 스프링 부트는 자동으로 스프링 빈 등록@AutowiredPlatformTransactionManagertransactionManager;
TransactionStatusstatus;
/** * 각각의 테스트 케이스 실행 직전 호출 * 여기서 트랜잭션 시작하면 됨 * 각각의 테스트를 트랜잭션 범위 안에서 실행 */@BeforeEachvoidbeforeEach(){
//트랜잭션 시작status = transactionManager.getTransaction(newDefaultTransactionDefinition());
}
/** * 각각의 테스트 케이스 실행완료 후 호출 * 여기서 트랜잭션을 롤백하면 됨 * 그러면 트랜잭션 실행 전 상태 복구 가능 * */@AfterEachvoidafterEach(){
//MemoryItemRepository 의 경우 제한적 사용if(itemRepositoryinstanceofMemoryItemRepository){
((MemoryItemRepository) itemRepository).clearStore();
}
//트랜잭션 롤백transactionManager.rollback(status);
}
}
**테스트@Transactional**
> 스프링은테스트데이터초기화를위해트랜잭션을적용하고롤백하는방식을@Transactional어노테이션하나로해결packagehello.itemservice.domain;
importhello.itemservice.repository.ItemRepository;
importhello.itemservice.repository.memory.MemoryItemRepository;
importorg.junit.jupiter.api.AfterEach;
importorg.junit.jupiter.api.BeforeEach;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.boot.test.context.SpringBootTest;
importorg.springframework.transaction.PlatformTransactionManager;
importorg.springframework.transaction.TransactionStatus;
importorg.springframework.transaction.annotation.Transactional;
importorg.springframework.transaction.support.DefaultTransactionDefinition;
@Transactional@SpringBootTestclassItemRepositoryTest2 {
@AutowiredItemRepositoryitemRepository;
//트랜잭션 관련 코드//트랜잭션 관리자는 PlatformTransactionManager 주입 받아서 사용, 스프링 부트는 자동으로 스프링 빈 등록@AutowiredPlatformTransactionManagertransactionManager;
TransactionStatusstatus;
/** * 각각의 테스트 케이스 실행 직전 호출 * 여기서 트랜잭션 시작하면 됨 * 각각의 테스트를 트랜잭션 범위 안에서 실행 @BeforeEach void beforeEach(){ //트랜잭션 시작 status = transactionManager.getTransaction(new DefaultTransactionDefinition()); }*//** * 각각의 테스트 케이스 실행완료 후 호출 * 여기서 트랜잭션을 롤백하면 됨 * 그러면 트랜잭션 실행 전 상태 복구 가능 * */@AfterEachvoidafterEach(){
//MemoryItemRepository 의 경우 제한적 사용if(itemRepositoryinstanceofMemoryItemRepository){
((MemoryItemRepository) itemRepository).clearStore();
}
//트랜잭션 롤백//transactionManager.rollback(status);
}
}
테스트 로직 실행, 테스트가 끝날 때 까지 모든 로직은 트랜잭션 안에서 수행 -> 트랜잭션은 기본적으로 전파되기 때문에, 리포지토
리에서 사용하는 JdbcTemplate도 같은 트랜잭션 사용
테스트 실행 중에 INSERT SQL 사용, item1, item2, item3 데이터베이스에 저장 -> 물론 테스트가 리포지토리 호출, 리포지토리는
JdbcTemplate을 사용해서 데이터 저장
검증을 위해서 SELECT SQL 데이터 조회, 여기서는 앞서 저장한 item1, item2, item3이 조회, SELECT SQL도 같은 트랜잭션을 사용하기 때문에 저장한 데이터 조회 가능, 다른 트랜잭션에서는 해당 데이터 확인할 수 없음, 여기서 assertThat()으로 검증 끝남
롤백에 의해 앞서 데이터베이스에 저장한 item1, item2, item3의 데이터가 제거
참고
테스트 케이스 메서드나 클래스 @Transaciotnal 직접 붙여 사용할 때만 동작
트랜잭션을 테스트에서 시작하기 때문에 서비스, 리포지토리에 있는 @Transaciotnal도 테스트에서 시작한 트랜잭션 참여
정리
테스트가 끝난 후 개발자가 직접 데이터를 삭제하지 않아도 되는 편리함 제공
테스트 실행 중, 데이터를 등록하고 중간에 테스트가 강제 종료되어도 걱정 없음, 트랜잭션을 커밋 하지 않기 때문에, 데이터는 자동
으로 롤백 됨(보통 데이터베스 커넥션이 끊어짐 자동으로 롤백되어 버림)
트랜잭션 범위 안에서 테스트를 진행하기 때문에 동시에 다른 테스ㅡ가 진행되어도 서로 영향을 주지 않는 장점이 있음
강제 커밋 @Commit
-@transactional을 테스트에서 사용하고 테스트가 끝나면 바로 롤백되기 때문에 저장한 데이터 사라짐, 최종 결과를 확인하고 싶을 때 @Commit을 클래스 또는 메서드에 붙이면 호출 됨, 참고(@Rollback(value = false)) 사용해도 됨
테스트 - 임베디드(끼워넣다) 모드DB
복잡한 DB 설정이나 서버 설치 없이, 코드만 실행하면 바로 사용할 수 있어서 빠르게 테스트하고 개발 중 디버깅 좋음
DB 설치 필요 없음, 테스트 끝나면 데이터도 날아가서 클린한 상태 유지
packagehello.itemservice;
@Slf4j//@Import(MemoryConfig.class)//@Import(JdbcTemplateV1Config.class)//@Import(JdbcTemplateV2Config.class)@Import(JdbcTemplateV3Config.class)
@SpringBootApplication(scanBasePackages = "hello.itemservice.web")
publicclassItemServiceApplication {
publicstaticvoidmain(String[] args) {
SpringApplication.run(ItemServiceApplication.class, args);
}
@Bean@Profile("local")
publicTestDataInittestDataInit(ItemRepositoryitemRepository) {
returnnewTestDataInit(itemRepository);
}
@Bean@Profile("test") //프로필이 test인 경우에만 데이터 소스 스프링 빈 등록, test case에서만 데이터소스를 스프링 빈으로 등록해서 사용publicDataSourcedataSource() {
log.info("메모리 데이터베이스 초기화");
//이 데이터소스를 사용하면 메모리 DB를 사용할 수 있음DriverManagerDataSourcedataSource = newDriverManagerDataSource();
dataSource.setDriverClassName("org.h2.Driver");
dataSource.setUrl("jdbc:h2:mem:db;DB_CLOSE_DELAY=-1");
dataSource.setUsername("sa");
dataSource.setPassword("");
returndataSource;
}
}
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
테스트 - 데이터베이스 분리
1. jdbc:h2:tcp://localhost/
/test local에서 접근하는 서버 전용 데이터베이스/testcase test 케이스에서 사용하는 전용 데이터베이스2. jdbc:h2:tcp://localhost/
테이블 생성하기
main-application.properties

test-application.properties
테스트 중요 원칙
테스트 - 데이터 롤백
테스트 실행 전 후 동작, @beforeeach, @AfterEach 기능 제공
@transactional이 적용된 테스트
리에서 사용하는 JdbcTemplate도 같은 트랜잭션 사용
JdbcTemplate을 사용해서 데이터 저장
참고
정리
으로 롤백 됨(보통 데이터베스 커넥션이 끊어짐 자동으로 롤백되어 버림)
강제 커밋 @Commit
-@transactional을 테스트에서 사용하고 테스트가 끝나면 바로 롤백되기 때문에 저장한 데이터 사라짐, 최종 결과를 확인하고 싶을 때 @Commit을 클래스 또는 메서드에 붙이면 호출 됨, 참고(@Rollback(value = false)) 사용해도 됨
테스트 - 임베디드(끼워넣다) 모드DB
실행결과
All reactions