Closed peterlitvak closed 1 year ago
I've already explained it here in detail. Below is the solution for your specific case.
@RunWith(SpringRunner.class)
@DataJpaTest
@AutoConfigureEmbeddedDatabase(beanName = "readWriteDataSource")
public class MultipleDataSourcesTest {
@TestConfiguration // or @Configuration
static class Config {
@Bean
public DataSource readOnlyDataSource(DataSource readWriteDataSource) {
ReadOnlyDataSourceAdapter adapter = new ReadOnlyDataSourceAdapter();
adapter.setTargetDataSource(readWriteDataSource);
return adapter;
}
}
public static class ReadOnlyDataSourceAdapter extends DelegatingDataSource {
@Override
public Connection getConnection() throws SQLException {
Connection connection = super.getConnection();
connection.setReadOnly(true);
return connection;
}
@Override
public Connection getConnection(String username, String password) throws SQLException {
Connection connection = super.getConnection(username, password);
connection.setReadOnly(true);
return connection;
}
}
@Autowired
@Qualifier("readWriteDataSource")
private DataSource readWriteDataSource;
@Autowired
@Qualifier("readOnlyDataSource")
private DataSource readOnlyDataSource;
// class body...
}
Thank you! I ended up configuring tests to use actual data sources (defined in the app) connecting to the embedded Postgres. I used one of the tests you have as an example. It seems to work as expected.
Is this indeed the right way to do this:
public class EmbeddedPostgresInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
public static PostgreSQLContainer<?> postgresContainer = new PostgreSQLContainer<>("postgres:11-alpine");
static {
postgresContainer.start();
}
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
applicationContext.getEnvironment().getPropertySources().addFirst(new MapPropertySource(
"some_name", Map.of(
"datasource.rw.url", postgresContainer.getJdbcUrl(),
"datasource.rw.username", postgresContainer.getUsername(),
"datasource.rw.password", postgresContainer.getPassword(),
"datasource.ro.url", postgresContainer.getJdbcUrl(),
"datasource.ro.username", postgresContainer.getUsername(),
"datasource.ro.password", postgresContainer.getPassword()
)));
}
}
in the test:
@ExtendWith(SpringExtension.class)
@SpringBootTest
@ContextConfiguration(classes = MyTestConfiguration.class,
initializers = EmbeddedPostgresInitializer.class)
@AutoConfigureEmbeddedDatabase(type = POSTGRES, replace = NONE, refresh = AFTER_EACH_TEST_METHOD)
public class MyIntegTest {
...
}
Yes, that certainly looks functional. However, you don't actually use this library at all anymore, because the container you are starting this way is out of the control of this library. Which results in refresh = AFTER_EACH_TEST_METHOD
having no effect.
Will it still pull the container? Is there a better way to preserve the original data sources but have the library do its thing?
Will it still pull the container?
As I wrote, it will work fine. You just don't use this library and you will lose the benefits it brings.
Is there a better way to preserve the original data sources but have the library do its thing?
The library automatically replaces the original data sources with the testing ones. In general, this should not be a problem, because in most cases the app code refers to the DataSource
interface and in tests you rarely care about the specific implementation (e.g. HikariCP). However, no, the library does not allow the use of any specific connection pool in tests.
Thank you for the explanation!
I'm closing this issue is favor of #234, which seems to be similar.
I have two data sources configured for my test like so:
When I execute tests, the queries against
readWriteDataSource
are executing fine but fail with "relation xyz does not exist" errors on thereadOnlyDataSource
. What could be the problem here?