The issue I am seeing, is that @Transactional is causing a transaction to be created and rolled back, however the data is being carried over from one test to the next.
Versions in use:
implementation('org.springframework.boot:spring-boot-starter-data-jpa')
testCompile "org.testcontainers:testcontainers:1.12.1"
testCompile "org.testcontainers:mysql:1.12.1"
Code:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
@ContextConfiguration(initializers = {Java8RepoTests.Initializer.class})
@Slf4j
@Transactional
public class Java8RepoTests {
@ClassRule
public static MySQLContainer mysql = new MySQLContainer();
@BeforeClass
public static void setUpBeforeClass() throws Exception {
logger.info("setUpBeforeClass()");
mysql.start();
}
@AfterClass
public static void tearDownAfterClass() throws Exception {
logger.info("tearDownAfterClass()");
mysql.stop();
}
@Autowired
private EntityManagerFactory entityManagerFactory;
private EntityManager em;
@Before
public void setUp() throws Exception {
logger.info("setUp()");
em = entityManagerFactory.createEntityManager();
}
@After
public void tearDown() throws Exception {
logger.info("tearDown()");
em.close();
}
@Autowired UserRepository repository;
@Test
public void testOne() {
int count = Iterables.size(repository.findAll());
// count = 0 at this point
User user = new User();
user = FillWithTestData(user);
User targetUser = repository.save(user);
count = Iterables.size(repository.findAll());
// count = 1
}
@Test
public void testTwo() {
int count = Iterables.size(repository.findAll());
// count = 1 at this point, should be zero!
User user = new User();
User targetUser= repository.save(user);
// Exception thrown that user already exists
}
static class Initializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
@Override
public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
TestPropertyValues.of(
"spring.datasource.url=" + mysql.getJdbcUrl(),
"spring.datasource.username=" + mysql.getUsername(),
"spring.datasource.password=" + mysql.getPassword()
).applyTo(configurableApplicationContext.getEnvironment());
}
}
}
Log output:
2019-09-16 13:55:01.074 INFO 21456 --- [ main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
2019-09-16 13:55:07.936 INFO 21456 --- [ main] o.s.s.c.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor'
2019-09-16 13:55:08.372 WARN 21456 --- [ main] aWebConfiguration$JpaWebMvcConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning
2019-09-16 13:55:13.312 INFO 21456 --- [ main] o.s.t.c.t.TransactionContext : Began transaction (1) for test context [DefaultTestContext@7a22302c testClass = Java8RepoTests, testInstance = com.test.api.Java8RepoTests@4af50246, testMethod = testOne@Java8RepoTests, testException = [null], mergedContextConfiguration = [WebMergedContextConfiguration@45482f82 testClass = Java8RepoTests, locations = '{}', classes = '{class com.test.api.ApiApplication}', contextInitializerClasses = '[class com.test.api.Java8RepoTests$Initializer]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}', contextCustomizers = set[org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@5af3afd9, org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@5ffead27, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@1fa268de, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.web.client.TestRestTemplateContextCustomizer@222545dc], resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map['org.springframework.test.context.web.ServletTestExecutionListener.activateListener' -> true, 'org.springframework.test.context.web.ServletTestExecutionListener.populatedRequestContextHolder' -> true, 'org.springframework.test.context.web.ServletTestExecutionListener.resetRequestContextHolder' -> true]]; transaction manager [org.springframework.orm.jpa.JpaTransactionManager@448fa659]; rollback [true]
Hibernate: select user0_.id as id1_11_, user0_.created_date as created_2_11_, user0_.updated_date as updated_3_11_, user0_.created_by as created_4_11_, user0_.last_modified_by as last_mod5_11_, user0_.active as active6_11_, user0_.email as email7_11_, user0_.enabled as enabled8_11_, user0_.first_name as first_na9_11_, user0_.is_using2fa as is_usin10_11_, user0_.last_name as last_na11_11_, user0_.password as passwor12_11_ from users user0_
Hibernate: insert into users (created_date, updated_date, created_by, last_modified_by, active, email, enabled, first_name, is_using2fa, last_name, password) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Hibernate: select user0_.id as id1_11_, user0_.created_date as created_2_11_, user0_.updated_date as updated_3_11_, user0_.created_by as created_4_11_, user0_.last_modified_by as last_mod5_11_, user0_.active as active6_11_, user0_.email as email7_11_, user0_.enabled as enabled8_11_, user0_.first_name as first_na9_11_, user0_.is_using2fa as is_usin10_11_, user0_.last_name as last_na11_11_, user0_.password as passwor12_11_ from users user0_
Hibernate: select user0_.id as id1_11_0_, user0_.created_date as created_2_11_0_, user0_.updated_date as updated_3_11_0_, user0_.created_by as created_4_11_0_, user0_.last_modified_by as last_mod5_11_0_, user0_.active as active6_11_0_, user0_.email as email7_11_0_, user0_.enabled as enabled8_11_0_, user0_.first_name as first_na9_11_0_, user0_.is_using2fa as is_usin10_11_0_, user0_.last_name as last_na11_11_0_, user0_.password as passwor12_11_0_, credential1_.user_id as user_id1_9_1_, credential2_.id as credenti2_9_1_, credential2_.id as id1_2_2_, credential2_.created_date as created_2_2_2_, credential2_.updated_date as updated_3_2_2_, credential2_.created_by as created_4_2_2_, credential2_.last_modified_by as last_mod5_2_2_, credential2_.cloud_provider_id as cloud_pr8_2_2_, credential2_.access_key as access_k6_2_2_, credential2_.owner_id as owner_id9_2_2_, credential2_.secret_key as secret_k7_2_2_, credential2_.virtual_datacenter_id as virtual10_2_2_, cloudprovi3_.id as id1_1_3_, cloudprovi3_.created_date as created_2_1_3_, cloudprovi3_.updated_date as updated_3_1_3_, cloudprovi3_.name as name4_1_3_, user4_.id as id1_11_4_, user4_.created_date as created_2_11_4_, user4_.updated_date as updated_3_11_4_, user4_.created_by as created_4_11_4_, user4_.last_modified_by as last_mod5_11_4_, user4_.active as active6_11_4_, user4_.email as email7_11_4_, user4_.enabled as enabled8_11_4_, user4_.first_name as first_na9_11_4_, user4_.is_using2fa as is_usin10_11_4_, user4_.last_name as last_na11_11_4_, user4_.password as passwor12_11_4_, virtualdat5_.id as id1_13_5_, virtualdat5_.created_date as created_2_13_5_, virtualdat5_.updated_date as updated_3_13_5_, virtualdat5_.created_by as created_4_13_5_, virtualdat5_.last_modified_by as last_mod5_13_5_, virtualdat5_.blueprint_id as blueprin7_13_5_, virtualdat5_.name as name6_13_5_, virtualdat5_.organization_id as organiza8_13_5_, virtualdat5_.owner_id as owner_id9_13_5_, roles6_.user_id as user_id1_10_6_, role7_.id as role_id2_10_6_, role7_.id as id1_7_7_, role7_.created_date as created_2_7_7_, role7_.updated_date as updated_3_7_7_, role7_.title as title4_7_7_ from users user0_ left outer join user_credentials credential1_ on user0_.id=credential1_.user_id left outer join credentials credential2_ on credential1_.credential_id=credential2_.id left outer join cloud_providers cloudprovi3_ on credential2_.cloud_provider_id=cloudprovi3_.id left outer join users user4_ on credential2_.owner_id=user4_.id left outer join virtual_datacenters virtualdat5_ on credential2_.virtual_datacenter_id=virtualdat5_.id left outer join user_role roles6_ on user0_.id=roles6_.user_id left outer join role role7_ on roles6_.role_id=role7_.id where user0_.id=?
2019-09-16 13:55:14.781 INFO 21456 --- [ main] o.s.t.c.t.TransactionContext : Rolled back transaction for test: [DefaultTestContext@7a22302c testClass = Java8RepoTests, testInstance = com.test.api.Java8RepoTests@4af50246, testMethod = testOne@Java8RepoTests, testException = [null], mergedContextConfiguration = [WebMergedContextConfiguration@45482f82 testClass = Java8RepoTests, locations = '{}', classes = '{class com.test.api.ApiApplication}', contextInitializerClasses = '[class com.test.api.Java8RepoTests$Initializer]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}', contextCustomizers = set[org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@5af3afd9, org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@5ffead27, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@1fa268de, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.web.client.TestRestTemplateContextCustomizer@222545dc], resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map['org.springframework.test.context.web.ServletTestExecutionListener.activateListener' -> true, 'org.springframework.test.context.web.ServletTestExecutionListener.populatedRequestContextHolder' -> true, 'org.springframework.test.context.web.ServletTestExecutionListener.resetRequestContextHolder' -> true]]
2019-09-16 13:55:14.794 INFO 21456 --- [ main] o.s.t.c.t.TransactionContext : Began transaction (1) for test context [DefaultTestContext@7a22302c testClass = Java8RepoTests, testInstance = com.test.api.Java8RepoTests@34a99d8, testMethod = testTwo@Java8RepoTests, testException = [null], mergedContextConfiguration = [WebMergedContextConfiguration@45482f82 testClass = Java8RepoTests, locations = '{}', classes = '{class com.test.api.ApiApplication}', contextInitializerClasses = '[class com.test.api.Java8RepoTests$Initializer]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}', contextCustomizers = set[org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@5af3afd9, org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@5ffead27, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@1fa268de, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.web.client.TestRestTemplateContextCustomizer@222545dc], resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map['org.springframework.test.context.web.ServletTestExecutionListener.activateListener' -> true, 'org.springframework.test.context.web.ServletTestExecutionListener.populatedRequestContextHolder' -> true, 'org.springframework.test.context.web.ServletTestExecutionListener.resetRequestContextHolder' -> true]]; transaction manager [org.springframework.orm.jpa.JpaTransactionManager@448fa659]; rollback [true]
Hibernate: select user0_.id as id1_11_, user0_.created_date as created_2_11_, user0_.updated_date as updated_3_11_, user0_.created_by as created_4_11_, user0_.last_modified_by as last_mod5_11_, user0_.active as active6_11_, user0_.email as email7_11_, user0_.enabled as enabled8_11_, user0_.first_name as first_na9_11_, user0_.is_using2fa as is_usin10_11_, user0_.last_name as last_na11_11_, user0_.password as passwor12_11_ from users user0_
Hibernate: select roles0_.user_id as user_id1_10_0_, roles0_.role_id as role_id2_10_0_, role1_.id as id1_7_1_, role1_.created_date as created_2_7_1_, role1_.updated_date as updated_3_7_1_, role1_.title as title4_7_1_ from user_role roles0_ inner join role role1_ on roles0_.role_id=role1_.id where roles0_.user_id=?
Hibernate: select credential0_.user_id as user_id1_9_0_, credential0_.credential_id as credenti2_9_0_, credential1_.id as id1_2_1_, credential1_.created_date as created_2_2_1_, credential1_.updated_date as updated_3_2_1_, credential1_.created_by as created_4_2_1_, credential1_.last_modified_by as last_mod5_2_1_, credential1_.cloud_provider_id as cloud_pr8_2_1_, credential1_.access_key as access_k6_2_1_, credential1_.owner_id as owner_id9_2_1_, credential1_.secret_key as secret_k7_2_1_, credential1_.virtual_datacenter_id as virtual10_2_1_, cloudprovi2_.id as id1_1_2_, cloudprovi2_.created_date as created_2_1_2_, cloudprovi2_.updated_date as updated_3_1_2_, cloudprovi2_.name as name4_1_2_, user3_.id as id1_11_3_, user3_.created_date as created_2_11_3_, user3_.updated_date as updated_3_11_3_, user3_.created_by as created_4_11_3_, user3_.last_modified_by as last_mod5_11_3_, user3_.active as active6_11_3_, user3_.email as email7_11_3_, user3_.enabled as enabled8_11_3_, user3_.first_name as first_na9_11_3_, user3_.is_using2fa as is_usin10_11_3_, user3_.last_name as last_na11_11_3_, user3_.password as passwor12_11_3_, virtualdat4_.id as id1_13_4_, virtualdat4_.created_date as created_2_13_4_, virtualdat4_.updated_date as updated_3_13_4_, virtualdat4_.created_by as created_4_13_4_, virtualdat4_.last_modified_by as last_mod5_13_4_, virtualdat4_.blueprint_id as blueprin7_13_4_, virtualdat4_.name as name6_13_4_, virtualdat4_.organization_id as organiza8_13_4_, virtualdat4_.owner_id as owner_id9_13_4_, blueprint5_.id as id1_0_5_, blueprint5_.created_date as created_2_0_5_, blueprint5_.updated_date as updated_3_0_5_, blueprint5_.name as name4_0_5_, organizati6_.id as id1_3_6_, organizati6_.created_date as created_2_3_6_, organizati6_.updated_date as updated_3_3_6_, organizati6_.created_by as created_4_3_6_, organizati6_.last_modified_by as last_mod5_3_6_, organizati6_.name as name6_3_6_, organizati6_.user_id as user_id7_3_6_, user7_.id as id1_11_7_, user7_.created_date as created_2_11_7_, user7_.updated_date as updated_3_11_7_, user7_.created_by as created_4_11_7_, user7_.last_modified_by as last_mod5_11_7_, user7_.active as active6_11_7_, user7_.email as email7_11_7_, user7_.enabled as enabled8_11_7_, user7_.first_name as first_na9_11_7_, user7_.is_using2fa as is_usin10_11_7_, user7_.last_name as last_na11_11_7_, user7_.password as passwor12_11_7_ from user_credentials credential0_ inner join credentials credential1_ on credential0_.credential_id=credential1_.id inner join cloud_providers cloudprovi2_ on credential1_.cloud_provider_id=cloudprovi2_.id inner join users user3_ on credential1_.owner_id=user3_.id inner join virtual_datacenters virtualdat4_ on credential1_.virtual_datacenter_id=virtualdat4_.id inner join blueprints blueprint5_ on virtualdat4_.blueprint_id=blueprint5_.id inner join organizations organizati6_ on virtualdat4_.organization_id=organizati6_.id inner join users user7_ on virtualdat4_.owner_id=user7_.id where credential0_.user_id=?
Hibernate: insert into users (created_date, updated_date, created_by, last_modified_by, active, email, enabled, first_name, is_using2fa, last_name, password) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Hibernate: select user0_.id as id1_11_, user0_.created_date as created_2_11_, user0_.updated_date as updated_3_11_, user0_.created_by as created_4_11_, user0_.last_modified_by as last_mod5_11_, user0_.active as active6_11_, user0_.email as email7_11_, user0_.enabled as enabled8_11_, user0_.first_name as first_na9_11_, user0_.is_using2fa as is_usin10_11_, user0_.last_name as last_na11_11_, user0_.password as passwor12_11_ from users user0_
Hibernate: select user0_.id as id1_11_, user0_.created_date as created_2_11_, user0_.updated_date as updated_3_11_, user0_.created_by as created_4_11_, user0_.last_modified_by as last_mod5_11_, user0_.active as active6_11_, user0_.email as email7_11_, user0_.enabled as enabled8_11_, user0_.first_name as first_na9_11_, user0_.is_using2fa as is_usin10_11_, user0_.last_name as last_na11_11_, user0_.password as passwor12_11_ from users user0_
2019-09-16 13:55:14.886 INFO 21456 --- [ main] o.s.t.c.t.TransactionContext : Rolled back transaction for test: [DefaultTestContext@7a22302c testClass = Java8RepoTests, testInstance = com.test.api.Java8RepoTests@34a99d8, testMethod = testTwo@Java8RepoTests, testException = java.lang.AssertionError: expected:<1> but was:<2>, mergedContextConfiguration = [WebMergedContextConfiguration@45482f82 testClass = Java8RepoTests, locations = '{}', classes = '{class com.test.api.ApiApplication}', contextInitializerClasses = '[class com.test.api.Java8RepoTests$Initializer]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}', contextCustomizers = set[org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@5af3afd9, org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@5ffead27, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@1fa268de, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.web.client.TestRestTemplateContextCustomizer@222545dc], resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map['org.springframework.test.context.web.ServletTestExecutionListener.activateListener' -> true, 'org.springframework.test.context.web.ServletTestExecutionListener.populatedRequestContextHolder' -> true, 'org.springframework.test.context.web.ServletTestExecutionListener.resetRequestContextHolder' -> true]]
2019-09-16 13:55:16.077 INFO 21456 --- [ Thread-9] o.s.s.c.ThreadPoolTaskExecutor : Shutting down ExecutorService 'applicationTaskExecutor'
2019-09-16 13:55:16.087 INFO 21456 --- [ Thread-9] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
The log output shows the transaction is created and rolled back. However, the data from testOne is still in the database when testTwo executes.
Not sure where to go from here. Google results show some variations of the above test code which I have explored to no avail.