How can I make Spring testcontext framework use multiple data sources?
-
09-10-2019 - |
Question
I'm trying to integration test my application with Spring TestContext framework. I have done this by extending AbstractTransactionalJUnit4SpringContextTests
, as usual. However, my application has three different data sources (with names like xDataSource, yDataSource, zdataSource), så when I try to run the test, the autowiring of data source in AbstractTransactionalJUnit4SpringContextTests
won't work, since it looks for a Data Source with autowire-by-type, but finds three, so it does not know which one to choose.
Is there any way to get Spring TestContext Framework to use three data sources? If so; how?
Solution
OK, I figured it out. The answer to this question is twofold. Firstly, extending AbstractTransactionalJUnit4SpringContextTests
won't work. This is because it needs a single data source for creating the SimpleJdbcTemplate
for verifying stuff with simple JDBC queries in the test. Since I don't use this feature in this test, I could replace extends AbstractTransactionalJUnit4SpringContextTests
with the collowing configuration:
@ContextConfiguration(locations = "classpath:applicationContext.xml")
@RunWith(SpringJUnit4ClassRunner.class)
@TestExecutionListeners({
DependencyInjectionTestExecutionListener.class,
DirtiesContextTestExecutionListener.class,
TransactionalTestExecutionListener.class
})
@Transactional
public class IntegrationTest {
...
}
The combination of these annotations gives the same setup as extending AbstractTransactionalJUnit4SpringContextTests
.
The second part was understanding that since I have three data sources, I also need all three so be referenced by the same PlatformTransactionManager
. I have distributed transactions. This is impossible with a DataSourceTransactionManager
, so I had to use a JtaTransactionManager
.
OTHER TIPS
The AbstractTransactionalJUnit4SpringContextTests
class is autowired to a single data source only to allow the convenience of providing an injected JdbcTemplate
object. You can override the setDataSource(DataSource dataSource)
method from AbstractTransactionalJUnit4SpringContextTests
in your test subclass and specify the data source to use like this:
@Resource(name = "dataSource")
public void setDataSource(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
You just have to provide the name of the one data source Spring should use for the jdbcTemplate
convenience methods. If extending AbstractTransactionalJUnit4SpringContextTests
is more convenient than other methods mentioned above, then you can force it to work by just choosing one of your data sources.
I found these details in Spring Jira ticket #SPR-4634.
You can define one of the data-sources as primary="true"
in your xml, and it will be chosen.
If you need all threem then you cannot rely on autowiring - use ReflectionTestUtils
to set it manually in your tests.