Spring Data JPA的repository都是接口,怎么测试呢?
这篇文章就回答这个问题,我们测试选择TodoRepository
中的findBySearchTerm()
方法作为例子
依赖的pom文件如下:
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>3.2.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.1.6.RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.dbunit</groupId>
<artifactId>dbunit</artifactId>
<version>2.5.1</version>
<scope>test</scope>
<exclusions>
<exclusion>
<artifactId>junit</artifactId>
<groupId>junit</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.github.springtestdbunit</groupId>
<artifactId>spring-test-dbunit</artifactId>
<version>1.2.1</version>
<scope>test</scope>
</dependency>
下面配置集成测试需要的环境
步骤如下:
SpringJUnit4ClassRunner
来运行测试,这是一个Spring Test框架对JUnit进行定制过的运行器,通过@RunWith
来进行配置@ContextConfiguration
注解来实现DependencyInjectionTestExecutionListener
为测试对象提供依赖注入TransactionalTestExecutionListener
提供事务的支持DbUnitTestExecutionListener
提供了Spring Test DbUnit中包含的特性配置后的配置类如下:
import com.github.springtestdbunit.DbUnitTestExecutionListener;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestExecutionListeners;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {PersistenceContext.class})
@TestExecutionListeners({DependencyInjectionTestExecutionListener.class,
TransactionalTestExecutionListener.class,
DbUnitTestExecutionListener.class})
public class ITFindBySearchTermTest {
}
详情可了解各个类的JavaDoc
下面可以为Spring Data JPA的repository写测试了
步骤如下:
首先,注入要测试的repository,代码如下:
import com.github.springtestdbunit.DbUnitTestExecutionListener;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestExecutionListeners;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {PersistenceContext.class})
@TestExecutionListeners({DependencyInjectionTestExecutionListener.class,
TransactionalTestExecutionListener.class,
DbUnitTestExecutionListener.class})
public class ITFindBySearchTermTest {
@Autowired
private TodoRepository repository;
}
然后,创建DbUnit的dataset来初始化测试数据,我们使用XML格式的dataset文件,文件具有如下特点:
我们的dataset文件如下:
<dataset>
<todos id="1" created_by_user="createdByUser" creation_time="2014-12-24 11:13:28" description="description" modified_by_user="modifiedByUser" modification_time="2014-12-25 11:13:28" title="title" version="0"/>
<todos id="2" created_by_user="createdByUser" creation_time="2014-12-24 11:13:28" description="tiscription" modified_by_user="modifiedByUser" modification_time="2014-12-25 11:13:28" title="Foo bar" version="0"/>
</dataset>
DbUnit的dataset的更多格式请看DbUnit dataset formats.
然后,写测试,步骤如下:
@DatabaseSetup
注解来配置datasetfindBySearchTerm()
方法在使用“iTl”作为参数进行查询时返回一个对象findBySearchTerm()
方法在使用“iTl”作为参数进行查询时返回一个id为1的对象ITFindBySearchTerm
代码如下:
import com.github.springtestdbunit.DbUnitTestExecutionListener;
import com.github.springtestdbunit.annotation.DatabaseSetup;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestExecutionListeners;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
import static org.assertj.core.api.Assertions.assertThat;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {PersistenceContext.class})
@TestExecutionListeners({DependencyInjectionTestExecutionListener.class,
TransactionalTestExecutionListener.class,
DbUnitTestExecutionListener.class})
@DatabaseSetup("todo-entries.xml")
public class ITFindBySearchTermTest {
@Autowired
private TodoRepository repository;
@Test
public void findBySearchTerm_TitleOfFirstTodoEntryContainsGivenSearchTerm_ShouldReturnOneTodoEntry() {
List<Todo> searchResults = repository.findBySearchTerm("iTl");
assertThat(searchResults).hasSize(1);
}
@Test
public void findBySearchTerm_TitleOfFirstTodoEntryContainsGivenSearchTerm_ShouldReturnFirstTodoEntry() {
List<Todo> searchResults = repository.findBySearchTerm("iTl");
Todo found = searchResults.get(0);
assertThat(found.getId()).isEqualTo(1L);
}
}
@DatabaseSetup
有一下两点需要注意:
@DatabaseSetup
注解表在类上,否则,需要表在方法上扩展阅读
- Writing Tests for Data Access Code讲了怎样写干净的和可维护的数据库测试代码
- Spring From the Trenches: Using Null Values in DbUnit Datasets讲了在DbUnit的dataset中怎样使用null值以及为什么要使用它们
- Spring From the Trenches: Resetting Auto Increment Columns Before Each Test Method讲了怎样在测试方法运行前重置自动增长的列
总结一下:
DbUnitTestExecutionListener
将Spring Test DbUnit和Spring Test framework进行了集成@DatabaseSetup
注解P.S. 项目代码可在Github (query methods, JPA Criteria API, Querydsl)获取
还可访问更多Spring Data JPA tutorial教程