Ich habe eine Integrations- Test-Klasse für meine UserController
. Der Inhalt der folgenden Klasse ist:Transaktionen im Spring-Boot-Test nicht zurückgerollt
// 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();
}
}
Wenn ich diese Test-Klasse zweimal ausführen, das zweite Mal es nicht, weil es in der Datenbank mit Benutzername admin
(eindeutige Einschränkung) bereits ein Benutzer ist.
Ich teste gegen eine postgres
Datenbank, die die gleiche wie in meiner Produktionsumgebung ist. Die Anwendung verwendet Spring jdbcTemplate
für Datenbankvorgänge.
Meine Protokollierung produziert die folgenden Protokolle:
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
Meine Anwendungsfluss ist <request> --> <controller> --> <service with jdbcTemplate>
und die Dienste sind Annotation mit @Transactional
.
Ich bin wirklich mit diesem fest.
Eine Lösung fand nicht für mich arbeiten, war es eine PlatformTransactionManager
Bohne für die Testkonfiguration zu erstellen:
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
Haben Sie 'REQUIRES_NEW' auf Ihrer '@ Transactional'-Methode in Ihrer Serviceebene? – Patrick
@Patrick das funktioniert nicht – mmjmanders
ja, deshalb fragte ich. Dies könnte ein Problem sein. – Patrick