Java SpringHibernateH2JUnit测试-如何在启动时加载模式
我正在尝试为我的应用程序开发测试(我很晚才发现测试…),但我被卡住了,无法完成基本配置。我在谷歌上搜索了很多例子,没有一个让我满意,坦率地说,这让我有点困惑 我试图实现的是在测试开始时加载import.sql(这是来自现有MySQL模式的转储文件),并将其加载到H2数据库中 这是hibernate配置文件:Java SpringHibernateH2JUnit测试-如何在启动时加载模式,java,spring,hibernate,junit,h2,Java,Spring,Hibernate,Junit,H2,我正在尝试为我的应用程序开发测试(我很晚才发现测试…),但我被卡住了,无法完成基本配置。我在谷歌上搜索了很多例子,没有一个让我满意,坦率地说,这让我有点困惑 我试图实现的是在测试开始时加载import.sql(这是来自现有MySQL模式的转储文件),并将其加载到H2数据库中 这是hibernate配置文件: @Configuration @EnableTransactionManagement @ComponentScan({ "kamienica.feature" }) public clas
@Configuration
@EnableTransactionManagement
@ComponentScan({ "kamienica.feature" })
public class HibernateTestConfiguration {
@Autowired
ApplicationContext applicationContext;
@Bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
sessionFactory.setPackagesToScan(new String[] { "kamienica" });
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
@Bean(name = "dataSource")
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("org.h2.Driver");
dataSource.setUrl("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;"
+ "INIT=CREATE SCHEMA IF NOT EXISTS kamienica;DB_CLOSE_ON_EXIT=FALSE");
dataSource.setUsername("sa");
dataSource.setPassword("");
return dataSource;
}
private Properties hibernateProperties() {
Properties properties = new Properties();
properties.put("hibernate.dialect", "org.hibernate.dialect.H2Dialect");
properties.put("hibernate.hbm2ddl.auto", "update");
// this is where I tried to load script the first time:
// properties.put("hibernate.hbm2ddl.import_files", "kamienica.sql");
return properties;
}
@Bean
@Autowired
public HibernateTransactionManager transactionManager(SessionFactory s) {
HibernateTransactionManager txManager = new HibernateTransactionManager();
txManager.setSessionFactory(s);
return txManager;
}
}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { HibernateTestConfiguration.class })
public class BaseTest {
private EmbeddedDatabase db;
@Autowired
private SessionFactory sessionFactory;
//second attempt to load sql file
@Before
public void setUp() throws Exception {
db = new EmbeddedDatabaseBuilder().addScript("import.sql").build();
}
@After
public void tearDown() throws Exception {
SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.unbindResource(sessionFactory);
SessionFactoryUtils.closeSession(sessionHolder.getSession());
}
}
每次开始测试时,我都会收到一条消息:
org.hibernate.tool.hbm2ddl.DatabaseMetadata getTableMetadata信息:
HH000262:未找到表:公寓
当我试图检索任何内容时,会得到空/空值
我尝试在hibernate配置(通过hibernate属性)以及所有测试类计划扩展的超类中加载sql文件:
@Configuration
@EnableTransactionManagement
@ComponentScan({ "kamienica.feature" })
public class HibernateTestConfiguration {
@Autowired
ApplicationContext applicationContext;
@Bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
sessionFactory.setPackagesToScan(new String[] { "kamienica" });
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
@Bean(name = "dataSource")
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("org.h2.Driver");
dataSource.setUrl("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;"
+ "INIT=CREATE SCHEMA IF NOT EXISTS kamienica;DB_CLOSE_ON_EXIT=FALSE");
dataSource.setUsername("sa");
dataSource.setPassword("");
return dataSource;
}
private Properties hibernateProperties() {
Properties properties = new Properties();
properties.put("hibernate.dialect", "org.hibernate.dialect.H2Dialect");
properties.put("hibernate.hbm2ddl.auto", "update");
// this is where I tried to load script the first time:
// properties.put("hibernate.hbm2ddl.import_files", "kamienica.sql");
return properties;
}
@Bean
@Autowired
public HibernateTransactionManager transactionManager(SessionFactory s) {
HibernateTransactionManager txManager = new HibernateTransactionManager();
txManager.setSessionFactory(s);
return txManager;
}
}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { HibernateTestConfiguration.class })
public class BaseTest {
private EmbeddedDatabase db;
@Autowired
private SessionFactory sessionFactory;
//second attempt to load sql file
@Before
public void setUp() throws Exception {
db = new EmbeddedDatabaseBuilder().addScript("import.sql").build();
}
@After
public void tearDown() throws Exception {
SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.unbindResource(sessionFactory);
SessionFactoryUtils.closeSession(sessionHolder.getSession());
}
}
如何加载sql文件并准备H2数据库以执行测试?我希望这种spring引导方法将对您有所帮助。首先在项目根目录的src/test目录中创建一个resources目录(springboot的类路径)。 在此目录中,您将开始放置名为saydata.SQL的夹具SQL数据文件。 然后,在同一级别上创建application.properties文件(同一目录请参见屏幕截图)。应按如下所示填充此文件:
spring.datasource.url = jdbc:h2:~/test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
#spring.datasource.url: jdbc:mysql://localhost:3306/yourDB
#spring.datasource.username = root
#spring.datasource.password =
# Hibernate
hibernate.show_sql: true
#hibernate.dialect: org.hibernate.dialect.MySQL5Dialec
spring.jpa.hibernate.ddl-auto=none
截图:
现在是测试方法
@RunWith(SpringJUnit4ClassRunner.class)
....
@Autowired
private DataSource ds; //your application.properties
@Autowired
private WebApplicationContext context;
private static boolean loadDataFixtures = true;
private MockMvc mockMvc;
....
@Before
public void setupMockMvc() {
mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
}
@Before
public void loadDataFixtures() {
if (loadDataFixtures) {
ResourceDatabasePopulator populator = new ResourceDatabasePopulator(context.getResource("classpath:/data.sql"));
DatabasePopulatorUtils.execute(populator, ds);
loadDataFixtures = false;
}
}
@Test
public void yourmethod() {
assertEquals(3, repository.count()); //example
}
我希望这个春季启动的方法会对你有所帮助。首先在项目根目录的src/test目录中创建一个resources目录(springboot的类路径)。 在此目录中,您将开始放置名为saydata.SQL的夹具SQL数据文件。 然后,在同一级别上创建application.properties文件(同一目录请参见屏幕截图)。应按如下所示填充此文件:
spring.datasource.url = jdbc:h2:~/test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
#spring.datasource.url: jdbc:mysql://localhost:3306/yourDB
#spring.datasource.username = root
#spring.datasource.password =
# Hibernate
hibernate.show_sql: true
#hibernate.dialect: org.hibernate.dialect.MySQL5Dialec
spring.jpa.hibernate.ddl-auto=none
截图:
现在是测试方法
@RunWith(SpringJUnit4ClassRunner.class)
....
@Autowired
private DataSource ds; //your application.properties
@Autowired
private WebApplicationContext context;
private static boolean loadDataFixtures = true;
private MockMvc mockMvc;
....
@Before
public void setupMockMvc() {
mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
}
@Before
public void loadDataFixtures() {
if (loadDataFixtures) {
ResourceDatabasePopulator populator = new ResourceDatabasePopulator(context.getResource("classpath:/data.sql"));
DatabasePopulatorUtils.execute(populator, ds);
loadDataFixtures = false;
}
}
@Test
public void yourmethod() {
assertEquals(3, repository.count()); //example
}
没有任何输出或完整的stacktrace,我只能建议您:
@Test
方法。你怎么会犯这样的错误import.sql
是否在src/test/resources
文件夹中?(注意测试路径)单元
表的sql脚本部分吗如果所有这些都是真的,那么问题可能不在于加载sql,而在于如何使用它,或者脚本的内容,或者表的名称等等 没有任何输出或完整的stacktrace,我只能建议您:
@Test
方法。你怎么会犯这样的错误import.sql
是否在src/test/resources
文件夹中?(注意测试路径)单元
表的sql脚本部分吗如果所有这些都是真的,那么问题可能不在于加载sql,而在于如何使用它,或者脚本的内容,或者表的名称等等 经过长时间的“调查”,我得出结论,问题隐藏在DBUnit TestNG设置的某个地方 我决定保持它的简单性,并切换到JUnit测试 如果其他人可能有类似的问题,以下是适用于我的配置文件:
@Configuration
@EnableTransactionManagement
@ComponentScan({ "kamienica.feature" })
public class JUnitConfig {
@Bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
sessionFactory.setPackagesToScan(new String[] { "kamienica" });
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
@Bean(name = "dataSource")
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("org.h2.Driver");
dataSource.setUrl("jdbc:h2:mem:kamienica;MODE=MySQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE");
dataSource.setUsername("sa");
dataSource.setPassword("");
return dataSource;
}
private Properties hibernateProperties() {
Properties properties = new Properties();
properties.put("hibernate.dialect", "org.hibernate.dialect.H2Dialect");
properties.put("hibernate.hbm2ddl.auto", "create");
return properties;
}
@Bean
public HibernateTransactionManager transactionManager(SessionFactory s) {
HibernateTransactionManager txManager = new HibernateTransactionManager();
txManager.setSessionFactory(s);
return txManager;
}
}
现在只需在resources文件夹中插入import.sql文件。
我还发现,每个insert语句无论有多长都必须在一行中,否则将无法加载
最后是一个简单的测试类:
@ContextConfiguration(classes = { JUnitConfig.class })
@RunWith(SpringJUnit4ClassRunner.class)
public class ApartmentServiceTest extends AbstractServiceTest{
@Autowired
ApartmentService service;
@Test
public void getList() {
List<Apartment> list = service.getList();
System.out.println(list.toString());
assertEquals(5, list.size());
}
}
@ContextConfiguration(类={JUnitConfig.class})
@RunWith(SpringJUnit4ClassRunner.class)
公共类ApartmentServiceTest扩展了AbstractServiceTest{
@自动连线
公寓服务;
@试验
public void getList(){
List=service.getList();
System.out.println(list.toString());
assertEquals(5,list.size());
}
}
经过长时间的“调查”,我得出结论,问题隐藏在数据库单元TestNG设置的某个地方
我决定保持它的简单性,并切换到JUnit测试
如果其他人可能有类似的问题,以下是适用于我的配置文件:
@Configuration
@EnableTransactionManagement
@ComponentScan({ "kamienica.feature" })
public class JUnitConfig {
@Bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
sessionFactory.setPackagesToScan(new String[] { "kamienica" });
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
@Bean(name = "dataSource")
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("org.h2.Driver");
dataSource.setUrl("jdbc:h2:mem:kamienica;MODE=MySQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE");
dataSource.setUsername("sa");
dataSource.setPassword("");
return dataSource;
}
private Properties hibernateProperties() {
Properties properties = new Properties();
properties.put("hibernate.dialect", "org.hibernate.dialect.H2Dialect");
properties.put("hibernate.hbm2ddl.auto", "create");
return properties;
}
@Bean
public HibernateTransactionManager transactionManager(SessionFactory s) {
HibernateTransactionManager txManager = new HibernateTransactionManager();
txManager.setSessionFactory(s);
return txManager;
}
}
现在只需在resources文件夹中插入import.sql文件。
我还发现,每个insert语句无论有多长都必须在一行中,否则将无法加载
最后是一个简单的测试类:
@ContextConfiguration(classes = { JUnitConfig.class })
@RunWith(SpringJUnit4ClassRunner.class)
public class ApartmentServiceTest extends AbstractServiceTest{
@Autowired
ApartmentService service;
@Test
public void getList() {
List<Apartment> list = service.getList();
System.out.println(list.toString());
assertEquals(5, list.size());
}
}
@ContextConfiguration(类={JUnitConfig.class})
@RunWith(SpringJUnit4ClassRunner.class)
公共类ApartmentServiceTest扩展了AbstractServiceTest{
@自动连线
公寓服务;
@试验
public void getList(){
List=service.getList();
System.out.println(list.toString());
assertEquals(5,list.size());
}
}
我不知道这对你来说是不是太过分了,但是在CI/CD的情况下,你会使用类似Flyway的东西来管理你的DB模式,为测试DB构建它是非常高兴的。我不知道这对你来说是否太过分了,但在CI/CD的情况下,你会使用类似Flyway的东西来管理你的DB模式,它非常乐意为测试数据库构建它。