Spring Hibernate H2 Junit 测试 - 如何在启动时加载模式
Posted
技术标签:
【中文标题】Spring Hibernate H2 Junit 测试 - 如何在启动时加载模式【英文标题】:Spring Hibernate H2 Junit testing - how to load schema on start 【发布时间】:2016-07-25 12:59:56 【问题描述】:我正在尝试为我的应用程序开发测试(我很晚才发现这些测试......)但我被卡住了,基本配置也被卡住了。我用谷歌搜索了很多例子,但没有一个让我满意,坦率地说让我有点困惑。
我想要实现的是在测试开始时加载 import.sql(这是现有 mysql 模式的转储文件)并将其加载到 H2 数据库中。
这里是休眠配置文件:
@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;
每次我开始测试时都会收到一条消息:
org.hibernate.tool.hbm2ddl.DatabaseMetadata getTableMetadata 信息: HHH000262:找不到表:公寓
我在尝试检索任何内容时得到空/空值
我尝试在休眠配置(通过休眠属性)以及计划扩展的所有测试类的超类中加载 sql 文件:
@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 数据库以执行测试?
【问题讨论】:
我不知道这对你来说是不是有点过头了,但是在 CI/CD 的情况下,你会使用 Flyway 之类的东西来为你管理你的数据库模式,并且非常乐意构建它用于测试数据库。 【参考方案1】:我希望这个 Spring Boot 方法对您有所帮助。首先在项目根目录下的 src/test 目录下创建一个resources目录(springboot的类路径)。 在此目录中,您将开始放置名为 data.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
【讨论】:
【参考方案2】:没有任何输出或完整的堆栈跟踪,我唯一可以建议您的是:
-
您没有显示任何
@Test
方法。你是怎么得到这个错误的?
您的文件import.sql
在src/test/resources
文件夹中吗? (注意测试路径)
您的 sql 脚本格式是否正确?您是否尝试过在导出后运行?您能否发布创建 apartment
表的 sql 脚本部分?
如果一切都是真的,也许问题不在于加载sql,而在于它是如何使用的,或者脚本的内容,或者表的名称等等......
【讨论】:
【参考方案3】:经过长时间的“调查”,我得出的结论是问题隐藏在 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;
现在只需要在资源文件夹中插入 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());
【讨论】:
以上是关于Spring Hibernate H2 Junit 测试 - 如何在启动时加载模式的主要内容,如果未能解决你的问题,请参考以下文章
Spring Hibernate H2 Junit 测试 - 如何在启动时加载模式
Spring4 JUnit 测试:将 SQL 加载到 H2 数据库
使用 h2 进行 Spring Junit 测试 - 找不到表