我试图在测试Spring控制器时使用DBunit。测试初始化失败,因为我的数据集包含不是由实体定义的表/列。
查询是用nativeQuery = true
标志定义的,所以我不希望事情出错:
@Query(value = "select * from TEST_TABLE where TEST_COLUMN = '2'";, nativeQuery = true)
TestClass getTestClass();
Dataset.xml文件:
<?xml version="1.0" encoding="UTF-8"?>
<dataset>
<TEST_TABLE TEST_COLUMN="2"/>
</dataset>
测试类:
@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 { ... }
引用的"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;
}
}
错误:
org.dbunit.dataset.NoSuchTableException: APP_VER
at org.dbunit.database.DatabaseDataSet.getTableMetaData(DatabaseDataSet.java:305)
...
尽管我添加了属性"hibernate.hbm2ddl.auto=create-drop",但表似乎没有自己创建。有趣的是,如果数据集引用一个由实体定义的表,我就不会遇到这个问题:
@Entity
@Table(name = "users")
public class UserRecord { ... }
我通过指定DataSourceInitializer Bean来解决这个问题,该Bean运行用于设置表的sql文件:
@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;
}
}
在引用的SQL文件(src/test/resources/schemas/schema.sql
)中,我也尝试先删除表,以防它们已经由JPA/Hibernate创建。这也让我摆脱了任何我不想处理的约束:
drop table if exists EXAMPLE_TABLE;
create table EXAMPLE_TABLE
(
EXAMPLE_TABLE_ID NUMBER(20),
)
...
我最终的测试类配置看起来像这样:
@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;
...
}