'Use DBUnit in Spring without defined entities via "nativequery"

I am trying to use DBunit while testing a Spring controller. The tests fail to initialize because my dataset contains tables/columns which are not defined by an entity.

The queries are defined with the nativeQuery = true flag so I wouldn't expect things to go awry:

@Query(value = "select * from TEST_TABLE where TEST_COLUMN = '2'";, nativeQuery = true)
TestClass getTestClass();

The Dataset.xml file:

<?xml version="1.0" encoding="UTF-8"?>
<dataset>
    <TEST_TABLE TEST_COLUMN="2"/>
</dataset>

The Test Class:

@RunWith(SpringJUnit4ClassRunner.class)
@ActiveProfiles("test")
@ContextConfiguration(classes = {Application.class, RepoTestApplication.class})
@SpringBootTest(classes = MockServletContext.class)
@TestPropertySource(properties = {"server.port=8444","hibernate.hbm2ddl.auto=create-drop"})
@WebAppConfiguration
@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_CLASS)
@TestExecutionListeners({DbUnitTestExecutionListener.class, DependencyInjectionTestExecutionListener.class,
        DirtiesContextBeforeModesTestExecutionListener.class})
@DatabaseSetup("classpath:datasets/Dataset.xml")
public class TestClassTest { ... }

The referenced "RepoTestApplication.class":

@Configuration
@EnableJpaRepositories
public class RepoTestApplication {
    
    @Bean
    public DataSource dataSource() {
        SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
        dataSource.setDriverClass(org.h2.Driver.class);
        dataSource.setUrl("jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE");
        dataSource.setUsername("sa");
        return dataSource;
    }

}

The Error:

org.dbunit.dataset.NoSuchTableException: APP_VER
    at org.dbunit.database.DatabaseDataSet.getTableMetaData(DatabaseDataSet.java:305)
    ...

It seems like the table doesn't create itself, even though I added the property "hibernate.hbm2ddl.auto=create-drop". Interestingly, I don't get this issue if the dataset references a table which is defined by an entity like:

@Entity
@Table(name = "users")
public class UserRecord { ... }


Solution 1:[1]

I overcame this by specifying a DataSourceInitializer Bean which runs a sql file for setting up tables:

@Configuration
public class RepoNativeQueryDataSourceInitializer {

    @Bean
    public DataSourceInitializer dataSourceInitializer(final DataSource dataSource) {
        ResourceDatabasePopulator resourceDatabasePopulator = new ResourceDatabasePopulator();
        resourceDatabasePopulator.addScript(new ClassPathResource("/schemas/schema.sql"));
        DataSourceInitializer dataSourceInitializer = new DataSourceInitializer();
        dataSourceInitializer.setDataSource(dataSource);
        dataSourceInitializer.setDatabasePopulator(resourceDatabasePopulator);
        return dataSourceInitializer;
    }

}

In the referenced SQL File (src/test/resources/schemas/schema.sql) I also attempt to delete the tables first in-case they were already created by JPA/Hibernate. This also let me get rid of any constraints which I didn't want to deal with:

drop table if exists EXAMPLE_TABLE;
create table EXAMPLE_TABLE
(
    EXAMPLE_TABLE_ID                 NUMBER(20),
)

...

My final test class configuration ended up looking like this:

@RunWith(SpringJUnit4ClassRunner.class)
@ActiveProfiles("test")
@SpringBootTest
@ContextConfiguration(classes = {Application.class, RepoTestApplication.class, RepoNativeQueryDataSourceInitializer.class})
@TestExecutionListeners({DbUnitTestExecutionListener.class, DependencyInjectionTestExecutionListener.class})
@TestPropertySource(properties = {"spring.jpa.properties.hibernate.show_sql=true", "server.port=8445"})
@DatabaseSetup("classpath:datasets/AllMyDataForTheTests.xml")
public class StuffRepositoryTest {

    @Autowired
    StuffRepository stuffRepository;

    ...
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 royka