Reputation: 3621
CONTEXT:
I have an existing Camel application. In order to test it with Spring Boot tools, it is wrapped into the Spring Boot framework and all tests run against this Spring Boot
app. Important: This code is used in production, so I am not allowed to change implementation and rewrite tests altogether. To test the app in a prod-like environment I use testcontainers
and Microsoft SQL Server in Docker, it is an additional functional tests module.
What I am trying to do is to spin up testcontainers
and update DataSource
, so it will point to SQL Server endpoint. I bumped into a never-ending series of problems. What am I doing wrong?
PROBLEM:
My SpringBootTestApplication
looks:
@SpringBootApplication
public class SpringBootTestApplication {
@Bean(name = "myDataSource")
public DataSource dataSource() throws ClassNotFoundException {
SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
dataSource.setDriverClass(Class.forName("org.apache.derby.jdbc.EmbeddedDriver").asSubclass(Driver.class));
dataSource.setUrl("jdbc:derby:memory:testdb;create=true");
dataSource.setUsername("sa");
dataSource.setPassword("");
Resource initSchema = new ClassPathResource("db/schema.sql");
ResourceDatabasePopulator databasePopulator = new ResourceDatabasePopulator(initSchema);
databasePopulator.setIgnoreFailedDrops(true);
DatabasePopulatorUtils.execute(databasePopulator, dataSource);
return dataSource;
}
public static void main(String[] args) {
SpringApplication.run(SpringBootTestApplication.class, args);
}
}
My test looks this way:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = SpringBootTestApplication.class)
@TestPropertySource("classpath:application-test.properties")
public class LargeDatabaseRetrieverTest {
@Rule
public MSSQLServerContainer mssqlServerContainer = (MSSQLServerContainer) new MSSQLServerContainer()
.withInitScript("db/test-data-mssql.sql")
.withExposedPorts(1433);
@Autowired
@Qualifier("myDataSource")
private DataSource dataSource;
@Before
public void setUp() throws Exception {
mssqlServerContainer.start();
DataSource mssqlDataSource = configureDataSource();
AutowireCapableBeanFactory factory = applicationContext.getAutowireCapableBeanFactory();
factory.autowireBean(mssqlDataSource);
}
@After
public void tearDown() throws Exception {
mssqlServerContainer.stop();
}
private DataSource configureDataSource() {
BasicDataSource basicDataSource = new BasicDataSource();
basicDataSource.setDriverClassName(mssqlServerContainer.getDriverClassName());
basicDataSource.setUrl(mssqlServerContainer.getJdbcUrl());
basicDataSource.setUsername(mssqlServerContainer.getUsername());
basicDataSource.setPassword(mssqlServerContainer.getPassword());
return basicDataSource;
}
@Test
public void test() {
// Use DataSource in here
}
}
I am trying to dynamically load DataSource
into a test, so I will test against MS SQL Server, not against default in-memory configuration.
The issue is that I don't know the configuration of MS SQL Server Docker container until it started and I cannot dynamically inject my own DataSource implementation.
LIST OF ATTEMPTED SOLUTIONS:
BeanPostProcessor
to reload beansNone of the above solutions work. It seems that I do something wrong and got lost between three birches. What am I doing wrong?
Upvotes: 0
Views: 3285
Reputation: 3063
Have you checked Spring Boot's docs on how to use it with Testcontainers? Or Testcontainers' Spring Boot example?
There is also a workshop.
Last but not least, if you only need an SQL database, you can use the JDBC URL support.
Upvotes: 1