spring JPA集成Junit单元测试
又有一段时间没有来记录点滴了,最近忙上了物联网平台项目,物联网平台何其多,我们定位于一个追赶者,说实在的心里没有啥谱。
项目中用到了spring boot,spring data JPA等一些相对部门较新的技术,spring boot真是个好东西,将spring 大部分的组件进行了集成,提供开箱即用的功能,还有约定大于配置的原则,让小白很轻松的去将框架搭建起来,接触它时感觉喜欢上了它。
接下来讲下spring JPA与Junit的集成如何进行单元测试。
参考资料
官方的资料权威,百度出来的要么质量不高,要么原来写的比较老,配置差别比较大了,再或者是本身这个问题太弱,哈哈
官方reference
官方示例
项目结构图
上在有个红叉叉就不纠结了,公司网络环境差,有个maven插件没弄好。
pom文件
这里主要列出核心部分
<!--继承父pom-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.3.RELEASE</version>
</parent>
<!--引入jpa starter-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!--引入test starter-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--使用mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
</dependency>
其实在这配置这个文件时踩了一个坑,在JPA中有个entitymanager
的概念去管理原来的数据库连接session
会话,开始采用了如下配置
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<exclusions>
<exclusion>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
</exclusion>
</exclusions>
</dependency>
后面测试一直报错找不到entitymanagerFactory
,其实明眼一看exclusion
是排除的意思,导致加载时datasource
没办法注入,在这种情况可能通过代码写Configuration
类或者配置XML文件。
编写DAO类
这里讲到的是JPA,讲主要的DAO类实现,DAO层的结构一般分为两层,一层为DAO接口,主要与驱动类找交道实现增删除改查、分页等功能,另一层是DAO模块与其它模块交互的service接口,这部分接口是不会怎么变化的,这样可以很好的抵抗数据库的变化而与外部模块之间的接口发生变化。
实体类TenantEntity
这里以一个简单租户的实体
@Entity
@Table(name = "tenant")
public class TenantEntity implements Serializable {
private static final long serialVersionUID = -6160322787230271783L;
@Id
@Column(name = "id")
private String id;
@Column(name = "name")
private String name;
@Column(name = "additional_info")
private String additionInfo;
public TenantEntity(){}
// TODO attributes get/set method
}
TenantDao接口
public interface TenantDao extends JpaRepository<TenantEntity, String> {
}
一咋看这就是个纯接口,那实现去哪里了呢,没错,后面的JPA帮你做了绝大部分数据库基本操作的功能,至于稍微详细原理性的探究看看这位博主写的spring-data-jpa详解
TenantService接口
一个简单的save方法
public interface TenantService {
public TenantEntity save(TenantEntity entity);
}
TenantServiceImpl实现
接口实现也炒鸡简单,日志木有,参数校验木有。。。。
@Service
public class TenantServiceImpl implements TenantService {
@Autowired
private TenantDao tenantDao;
public TenantEntity save(TenantEntity entity) {
return tenantDao.save(entity);
}
}
编写测试类
上面的被测代码基本写完了,接下来准备测试代码
配置加载类
配置加载类其实是个空类,但用到了一个关键的注解@SpringBootApplication
,这个老牛了,是三个注解的总和@Configuration,@EnableAutoConfiguration,@ComponentScan,其实这个空类是为了拉起spring窗口,并且将扫描到的bean进行自动配置,以及数据源参数的配置,想想都方便,不过方便的同时就是隐藏了很多细节,不懂原理的话刚开始会比较痛苦。另外有个疑问扫描的包路径是什么呢,就是以这个空类所在的包为基准,对以后的子包进行搜索。
@SpringBootApplication
public class AppConfiguration
{
}
测试基类
为什么要写测试基类呢,其实是为了方便代码的复用与维护,不用每个测试类头上写配置的注解,另外也可以将测试用到的较通用的方法放到里面去。
@RunWith(SpringJUnit4ClassRunner.class)
@TestPropertySource(locations = {"classpath:application-test.properties"})
@SpringBootTest
public abstract class AbstractServiceTest {
@Autowired
protected TenantService tenantService;
protected TenantEntity generateTenant(){
TenantEntity tenant = new TenantEntity();
tenant.setId("130");
tenant.setName("test");
tenant.setAdditionInfo("comba");
return tenant;
}
}
测试类
直接贴代码了
public class TenantServiceImplTest extends AbstractServiceTest {
@Test
public void saveTenant(){
TenantEntity tenant = generateTenant();
TenantEntity newTenant = tenantService.save(tenant);
Assert.assertEquals(tenant.getId(), newTenant.getId());
Assert.assertEquals(tenant.getName(), newTenant.getName());
}
}
编写配置文件
配置文件是指配置一些常用参数,数据库配置参数等。
spring.datasource.url=jdbc:mysql://172.16.18.101:3306/iot?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
# JPA (JpaBaseConfiguration, HibernateJpaAutoConfiguration)
spring.data.jpa.repositories.enabled=true
spring.jpa.generate-ddl=false
spring.jpa.hibernate.ddl-auto=update
spring.jpa.open-in-view=true
spring.jpa.show-sql=true
这样就可以跑起来了。
后话
这个例子比较简单,只提供了一种使用方式与基本思路,如有更高明的方法,望交流共勉。
推荐阅读
-
Spring boot 集成Junit单元测试
-
spring JPA集成Junit单元测试
-
Spring Boot 单元测试JUnit的实践
-
SpringBoot集成Spring Data JPA及读写分离
-
Spring Boot 单元测试JUnit的实践
-
SpringBoot集成Spring Data JPA及读写分离
-
用Spring集成的JOTM配置分布式事务,结合hibernate jpa 博客分类: mysqlhibernatespringsqlserveroracle
-
基于spring boot 1.5.4 集成 jpa+hibernate+jdbcTemplate(详解)
-
基于spring boot 1.5.4 集成 jpa+hibernate+jdbcTemplate(详解)
-
详解Spring Boot Junit单元测试