5

Consider the typical DBUnit Spring Test (see https://github.com/springtestdbunit/spring-test-dbunit) :

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {
"classpath:/META-INF/spring/applicationContext-database.xml",
"classpath:spring-*.xml"
})
@TestExecutionListeners({ DependencyInjectionTestExecutionListener.class,
    DirtiesContextTestExecutionListener.class,
    TransactionalTestExecutionListener.class,
    DbUnitTestExecutionListener.class })
@DatabaseSetup("/dbunit/data.xml")
public class UnitTest {

    @Autowired
    private UnitUnderTest uut;

    @Test
    public void shouldInitDB() {
         ...
    }
}

What I have verified is that, and has expected, Autowiring will happen before DatabaseSetup. This must happen because DBUnit depends on the application context to provide the configured data source.

The problem is that the UnitUnderTest bean has a @PostConstruct where it loads some data from the DB but, since the Autowiring happens before the DBunit setup, the data will not be available at this stage.

Any ideas on how to solve this issue in a clean way?

Bruno Santos
  • 1,530
  • 1
  • 15
  • 22

3 Answers3

1

You can you Spring's ResourceDatabasePopulator.

I think you can use something like this

@PostConstruct
public void myInMemryPopulator() {
final ResourceDatabasePopulator databasePopulator = new ResourceDatabasePopulator();

        try {

            Resource[] array = resourceResolver.getResources("classpath:/*.sql");       

            for (Resource resource : array) {

                databasePopulator.addScript(resource);
            }
            databasePopulator.populate(dataSource.getConnection());

        } catch (IOException | SQLException e) {
            LOGGER.error("Error in databasePopulator  {} ", e);
        }

    } 
Eric Aya
  • 69,473
  • 35
  • 181
  • 253
Niraj Sonawane
  • 10,225
  • 10
  • 75
  • 104
0

You can have a setup method in your test class and call the post construct method manually. That will work.

Eshan Sudharaka
  • 607
  • 2
  • 9
  • 16
  • I'm afraid that is a non-solution! In such case I would have to pass the responsibility of calling that method to some other bean. I don't think that there's the need to do that. I'm hopping that spring-test-dbunit will have a cleaner, less intrusive way of testing this kind of scenario, which I'm sure will not be that rare. – Bruno Santos Nov 27 '13 at 01:43
  • My postconstruct method tries to retrieve database object and it breaks while autowiring, so this solution won't help. – TheBakker Sep 04 '15 at 09:49
0

Lazy initialization helped me, I added @Lazy over the @Component* and over the @Autowired in injection points

@Lazy
@Component
public class UnitUnderTestImpl {
...
}

@Lazy
@Autowired
private UnitUnderTest uut;
tosha
  • 1