博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
使用内存数据库进行单元测试
阅读量:4878 次
发布时间:2019-06-11

本文共 6607 字,大约阅读时间需要 22 分钟。

转自:https://gerrydevstory.com/2014/04/11/unit-testing-using-mysql-in-memory-database-on-spring/

Unit Testing Using In-Memory MySQL Database On Spring

Well the title lied, there’s no such thing as in-memory MySQL database (or at least I won’t be using it for this article). Instead I will use H2 in-memory database setup to run in “MySQL mode”

1
2
3
4
<
bean
id
=
"dataSource"
class
=
"org.apache.commons.dbcp.BasicDataSource"
>
  
<
property
name
=
"driverClassName"
value
=
"org.h2.Driver"
/>
  
<
property
name
=
"url"
value
=
"jdbc:h2:mem:testdb;MODE=MySQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE"
/>
</
bean
>

(thanks to joensson for )

If your app just uses plain jdbc then adding above datasource to your test context would be sufficient, but if you use JPA/Hibernate the cost of table setup, scanning etc could be quite significant.

To overcome this you can split the test context using @ContextHierarchy annotation.

In the example below I have unit tests for two DAOs: AccountDAOTest and CustomerDAOTest:

1
2
3
4
5
6
7
@ContextHierarchy
({
  
@ContextConfiguration
(
"/test-root-context.xml"
),
  
@ContextConfiguration
(
"AccountDAOTest-context.xml"
)
})
@RunWith
(SpringJUnit4ClassRunner.
class
)
public
class
AccountDAOTest {
}
1
2
3
4
5
6
7
@ContextHierarchy
({
  
@ContextConfiguration
(
"/test-root-context.xml"
),
  
@ContextConfiguration
(
"CustomerDAOTest-context.xml"
)
})
@RunWith
(SpringJUnit4ClassRunner.
class
)
public
class
CustomerDAOTest {
}

By doing this Spring test-root-context.xml will be setup once and reused accross all unit tests. Only put components common to all tests in test-root-context.xml. In my case I put the following:

  • DataSource
  • EntityManagerFactory
  • TransactionManager
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!-- JDBC Data Source -->
<
bean
id
=
"dataSource"
class
=
"org.apache.commons.dbcp.BasicDataSource"
>
  
<
property
name
=
"driverClassName"
value
=
"org.h2.Driver"
/>
  
<
property
name
=
"url"
value
=
"jdbc:h2:mem:testdb;MODE=MySQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE"
/>
</
bean
>
 
 
<!-- EntityManagerFactory -->
<
bean
class
=
"org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
id
=
"entityManagerFactory"
>
  
<
property
name
=
"persistenceUnitName"
value
=
"persistenceUnit"
/>
  
<
property
name
=
"dataSource"
ref
=
"dataSource"
/>
</
bean
>
 
<!-- Transaction Manager -->
<
bean
class
=
"org.springframework.orm.jpa.JpaTransactionManager"
id
=
"transactionManager"
>
  
<
property
name
=
"entityManagerFactory"
ref
=
"entityManagerFactory"
/>
</
bean
>

All test specific components go into their respective context.

Don’t forget to add <tx:annotation-driven/> if your DAO uses it. This can’t be placed on test-root-context.xml because I don’t scan all my DAOs there.

And lastly — ofcourse — you need to make sure your pom.xml has dependency to spring-test, junit and h2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<
dependency
>
  
<
groupId
>com.h2database</
groupId
>
  
<
artifactId
>h2</
artifactId
>
  
<
version
>1.3.176</
version
>
  
<
scope
>test</
scope
>
</
dependency
>
 
<
dependency
>
  
<
groupId
>org.springframework</
groupId
>
  
<
artifactId
>spring-test</
artifactId
>
  
<
version
>${org.springframework-version}</
version
>
  
<
scope
>test</
scope
>
</
dependency
>
 
<
dependency
>
  
<
groupId
>junit</
groupId
>
  
<
artifactId
>junit</
artifactId
>
  
<
version
>4.7</
version
>
  
<
scope
>test</
scope
>
</
dependency
>

使用java代码进行bean的配置:

@Configuration

@EnableTransactionManagement(proxyTargetClass = true)
@EnableConfigurationProperties(value = {JpaProperties.class,DataSourceProperties.class})
public class MfgMasterInMemoryDBConfig {
// <!-- JDBC Data Source -->
// <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
// <property name="driverClassName" value="org.h2.Driver"/>
// <property name="url" value="jdbc:h2:mem:testdb;MODE=MySQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE" />
// </bean>
//
//
// <!-- EntityManagerFactory -->
// <bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory">
// <property name="persistenceUnitName" value="persistenceUnit" />
// <property name="dataSource" ref="dataSource" />
// </bean>
//
// <!-- Transaction Manager -->
// <bean class="org.springframework.orm.jpa.JpaTransactionManager" id="transactionManager">
// <property name="entityManagerFactory" ref="entityManagerFactory" />
// </bean>
@Autowired
private JpaProperties jpaProperties;
@Bean
public JpaVendorAdapter jpaVendorAdapter() {
return new HibernateJpaVendorAdapter();
}
@Bean
public EntityManagerFactoryBuilder entityManagerFactoryBuilder() {
return new EntityManagerFactoryBuilder(jpaVendorAdapter(), jpaProperties.getProperties(), null);
}

@Bean

public EntityManager entityManger(EntityManagerFactory factory) {
return factory.createEntityManager();
}
@Bean
public DataSource dataSource(DataSourceProperties baseDataSourceProperties){
DataSource dataSource = DataSourceBuilder
.create(baseDataSourceProperties.getClassLoader())
.driverClassName("org.h2.Driver")
.url("jdbc:h2:mem:testdb;MODE=MySQL")
.username("sa")
.password("")
.build();;
return dataSource;
}
@Bean JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory){
JpaTransactionManager jpaTransactionManager = new JpaTransactionManager();
jpaTransactionManager.setEntityManagerFactory(entityManagerFactory);
return jpaTransactionManager;
}
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource, EntityManagerFactoryBuilder builder) {
Map<String, Object> hibernateProps = new LinkedHashMap<>();
hibernateProps.putAll(jpaProperties.getHibernateProperties(dataSource));

return builder

.dataSource(dataSource)
.packages(User.class.getPackage().getName())
.properties(hibernateProps).jta(false)
.build();
}
}

 

Test类的主要注解:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes={MfgMasterTestConfiguration.class,MfgMasterInMemoryDBConfig.class})
//@SpringApplicationConfiguration(classes = MfgMasterDataApplication.class)
public class MfgMasterDataApplicationTests {
@Autowired
public DataSource dataSource;
@Before
public void prepareUser(){
try {
dataSource.getConnection().createStatement().executeUpdate("INSERT INTO user (id, email, password, created_by, creation_date, enabled, update_date, updated_by, version, firstname, lastname, language) "
+ "VALUES (-1, 'system@mfg.com', 'system', -1, '2015-03-02 17:36:38', 0, NULL, NULL, 0, 'system', 'system', 'US')");
} catch (SQLException e) {
e.printStackTrace();
}
}
@Test
public void contextLoads() {
System.out.println("Done");
}

}

转载于:https://www.cnblogs.com/ly-radiata/p/5212676.html

你可能感兴趣的文章
精挑细选 NYOJ 263
查看>>
java容器简要概述
查看>>
python之Queue
查看>>
[Bzoj5043][Lydsy1709月赛]密码破译(按位dp)
查看>>
并发和多线程(四)--锁状态概念
查看>>
保持顺序去重
查看>>
20135213 20135231 信息安全系统设计基础课程第四次实验报告
查看>>
PyChram中同目录下import引包报错的解决办法?
查看>>
HNOI200——营业额统计(splay/treap)
查看>>
python练习题1-一元二次方程解
查看>>
小程序获取网络类型代码
查看>>
HTTP协议概述
查看>>
[zz]AVL树
查看>>
CF1143F/1142C U2
查看>>
mysql安装
查看>>
树莓派静态IP配置
查看>>
ASHX 控制类的HttpContext.Response 输出不完整的问题
查看>>
Visual Studio 2017中"const char *" 类型的值不能用于初始化 "char *" 类型的实体
查看>>
实时Web与WebSocket实践
查看>>
Equals()和GetHashCode()方法深入了解
查看>>