I'm NOT looking for a solution to this problem (it is @DirtiesContext), I want to understand WHY this happens depending on the execution order, or if it is a bug.
I have two classes that look exactly the same: one called SpringExtensionTest and the other ThisAnotherClassTest, both look like this:
@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = {H2JpaConfiguration.class})
class SpringExtensionTest {
@Autowired
private PersonRepository personRepository;
@Test
void name() {
assertEquals(0, personRepository.count());
Person testing = personRepository.save(new Person(UUID.randomUUID(), "first", "second"));
assertNotNull(testing.getId());
}
}
And I have another class that is called MySpecialTest that uses @SpringBootTest
@SpringBootTest
@ActiveProfiles("qa")
@TestPropertySource(properties = "logging.level.org.springframework.*=DEBUG")
public class MySpecialTest {
@Autowired
ApplicationContext applicationContext;
@Autowired
private PersonRepository personRepository;
@Test
void name() {
assertEquals(0, personRepository.count());
Person testing = personRepository.save(new Person(UUID.randomUUID(), "first", "second"));
String[] activeProfiles = applicationContext.getEnvironment().getActiveProfiles();
for (String activeProfile : activeProfiles) {
System.out.println(activeProfile);
}
}
}
This is the config class
@TestConfiguration
@EnableJpaRepositories(basePackages = "com.example.spring_batch_demo")
public class H2JpaConfiguration {
@Bean(destroyMethod = "shutdown")
public EmbeddedDatabase dataSource() {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.build();
}
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource);
em.setPackagesToScan("com.example.spring_batch_demo");
em.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
Properties properties = new Properties();
properties.setProperty("hibernate.hbm2ddl.auto", "create-drop");
properties.setProperty("hibernate.dialect", "org.hibernate.dialect.H2Dialect");
em.setJpaProperties(properties);
return em;
}
@Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
return new JpaTransactionManager(entityManagerFactory);
}
}
If the order of execution is:
Scenario 1: SpringExtensionTest, ThisAnotherClassTest, MySpecialTest
Scenario 2: SpringExtensionTest, MySpecialTest, ThisAnotherClassTest
I want to understand how/why this is happening.
EDIT:
Scenario 3: same as Scenario2 but set a name to the database in H2JpaConfiguration
@Bean(destroyMethod = "shutdown")
public EmbeddedDatabase dataSource() {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.setName(UUID.randomUUID().toString()) // SET NAME TO DB
.build();
}
I found the answer myself, but will write here so anyone can reference.
EmbeddedDatabaseFactory
has a default name if you don't specify one all the contexts will use the same database and not create new ones. But there is a tricky case that made this scenario 2 possible.
Scenario 1:
Scenario 2:
@SpringBootTest
this context will drop tables registered in JPA, we can see it in the logs org.hibernate.SQL: drop table if exists person cascade
.
@SpringBootTest
context all the tests runs inside transactions, so even if saving a person to the database it is rolled back after each test.Scenario 3: