스프링 부트 테스트의 트랜잭션이 롤백되지 않음
통합 테스트 수업이 있습니다.UserController다음 수업의 내용은 다음과 같습니다.
// imports...
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@RunWith(SpringRunner.class)
@Transactional
@Rollback
public class UserControllerTests {
private static final String ENDPOINT = "/v1/users";
@Autowired
private TestRestTemplate restTemplate;
@Autowired
private ApplicationProperties applicationProperties;
@Test
public void test_user_create() {
String token = login("test", "test");
HttpEntity<UserRequest> request = createRequest(token, "admin", "admin");
ResponseEntity<User> response = restTemplate.exchange(ENDPOINT, HttpMethod.POST, request, User.class);
assertEquals(HttpStatus.CREATED, response.getStatusCode());
}
private HttpEntity createRequest(String token) {
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
headers.set("Authorization", String.format("Bearer %s", token));
return new HttpEntity(headers);
}
private HttpEntity<UserRequest> createRequest(String token, String username, String password) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
headers.set("Authorization", String.format("Bearer %s", token));
return new HttpEntity<>(new UserRequest(username, password), headers);
}
private String login(String username, String password) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
headers.set("Authorization", String.format("Basic %s", Base64.getEncoder().encodeToString(String.format("%s:%s", applicationProperties.getAuth().getClientId(), applicationProperties.getAuth().getClientSecret()).getBytes())));
MultiValueMap<String, String> body = new LinkedMultiValueMap<>();
body.add("grant_type", "password");
body.add("username", username);
body.add("password", password);
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(body, headers);
ResponseEntity<OAuth2AccessToken> response = restTemplate.exchange("/oauth/token", HttpMethod.POST, request, OAuth2AccessToken.class);
return response.getBody().getValue();
}
}
이 테스트 클래스를 두 번 실행하면 데이터베이스에 사용자 이름을 가진 사용자가 이미 있기 때문에 두 번째 테스트 클래스가 실패합니다.admin(확장 제약 조건).
에 대해 테스트 중입니다.postgres운영 환경과 동일한 데이터베이스입니다.응용 프로그램이 Spring's를 사용하고 있습니다.jdbcTemplate데이터베이스 작업에 사용됩니다.
로깅을 통해 다음 로그가 생성되었습니다.
2017-10-13 14:11:31.407 INFO [iam-service,,,] 63566 --- [ main] o.s.t.c.transaction.TransactionContext : Began transaction (1) for test context
...
2017-10-13 14:11:32.050 INFO [iam-service,,,] 63566 --- [ main] o.s.t.c.transaction.TransactionContext : Rolled back transaction for test context
내 지원 흐름은<request> --> <controller> --> <service with jdbcTemplate>그리고 그 서비스들은 주석을 달았습니다.@Transactional.
저는 정말로 이것에 얽매여 있습니다.
발견된 한 가지 솔루션은 저에게 효과가 없었습니다. 이 솔루션은 다음과 같은 이점을 제공했습니다.PlatformTransactionManager테스트 구성을 위한 be:
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
공식 Spring Boot 설명서에 따르면 db 트랜잭션 롤백은 "웹 계층"에서 직접 적용할 때 지원되지 않습니다.
만약 당신의 테스트가
@Transactional기본적으로 각 테스트 방법이 끝날 때 트랜잭션을 롤백합니다.그러나, 이 협정을 다음 중 하나와 함께 사용할 때.RANDOM_PORT또는DEFINED_PORT암시적으로 실제 서블릿 환경을 제공합니다. HTTP 클라이언트와 서버는 별도의 스레드에서 실행되므로 트랜잭션이 분리됩니다.이 경우 서버에서 시작된 트랜잭션은 롤백되지 않습니다.
다음 옵션을 고려해 볼 것을 제안합니다.
통합 테스트를 수행할 때 테스트 방법 실행 후 테이블 만들기/복원 & Drop/Clear.이 접근 방식은 DB 스키마가 클 때 상당한 오버헤드가 발생할 수 있지만 필요에 따라 데이터를 선택적으로 삭제/복원할 수 있습니다.
언급URL : https://stackoverflow.com/questions/46729849/transactions-in-spring-boot-testing-not-rolled-back
'codememo' 카테고리의 다른 글
| Oracle Sql Loader를 사용하여 타임스탬프 필드를 현재 타임스탬프로 채우는 방법 (0) | 2023.07.22 |
|---|---|
| 반복 가능한 크기의 덩어리를 일정한 크기로 분할하는 방법 (0) | 2023.07.22 |
| .py 파일과 .pyc 파일의 차이점은 무엇입니까? (0) | 2023.07.22 |
| 밀도로 채색된 산점도를 만들려면 어떻게 해야 합니까? (0) | 2023.07.22 |
| django-rest-framework serializer를 사용하여 외부 키 값을 검색하는 중 (0) | 2023.07.22 |