使用 DBUnit 集成测试 Spring 存储库层
Integration testing Spring repository layer with DBUnit
我一直在关注 Petri Kainulainen 的 this 非常有用的博客 post,使用 spring-data-jpa 和 DBUnit 为我的 Spring 存储库代码编写集成测试.
我的 bean 上下文 XML 是这样设置的
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">
<context:property-placeholder location="file:src/main/webapp/WEB-INF/config/application-test.properties"
ignore-resource-not-found="false" />
<bean id="dataSource" class="com.jolbox.bonecp.BoneCPDataSource">
<property name="driverClass" value="${db.driver}" />
<property name="jdbcUrl" value="${db.url}" />
<property name="username" value="${db.username}" />
<property name="password" value="${db.password}" />
</bean>
<bean id="directorRepository" name="directorRepositoryMock" class="org.mockito.Mockito"
factory-method="mock">
<constructor-arg value="com.tvfreakz.repository.DirectorRepository" />
</bean>
</beans>
我的数据集 XML 具有以下内容
<!DOCTYPE dataset SYSTEM "my-dataset.dtd">
<dataset>
<director directorid="1" director="Ridley Scott" />
<director directorid="2" director="James Cameron" />
<director directorid="3" director="David Fincher" />
<director directorid="4" director="Jean-Pierre Jeunet" />
</dataset>
这是存储库界面
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.tvfreakz.model.entity.Director;
@Repository("directorRepository")
public interface DirectorRepository extends JpaRepository<Director, Long> {
Director findByDirectorId(Long directorId);
}
我的测试class是这样设置的
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertEquals;
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.support.DirtiesContextTestExecutionListener;
import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
import com.github.springtestdbunit.DbUnitTestExecutionListener;
import com.github.springtestdbunit.annotation.DatabaseSetup;
import com.tvfreakz.model.entity.Director;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"file:src/main/webapp/WEB-INF/config/testMVCContext.xml"})
@TestExecutionListeners({ DependencyInjectionTestExecutionListener.class,
DirtiesContextTestExecutionListener.class,
TransactionalTestExecutionListener.class,
DbUnitTestExecutionListener.class })
@DatabaseSetup("testDataset.xml")
public class ITDirectorRepositoryTest {
@Autowired
private DirectorRepository repository;
@Test
public void testFindByDirectorIdWhenNoDirectorFound() {
Director director = repository.findByDirectorId(10L);
assertNull(director);
}
@Test
public void testFindByDirectorIdWhendirectorIsFound() {
Director director = repository.findByDirectorId(1L);
assertEquals("Ridley Scott", director.getDirectorName());
}
}
我期待 @DatabaseSetup
注释采用我的配置并将所有表和数据插入设置到由 dataSource
bean 配置的测试数据库中。
这似乎什么都不做(即数据库保持空白,没有表或数据),我的第二个测试 testFindByDirectorIdWhendirectorIsFound
失败,因为返回的 director 为空。我错过了什么?
编辑 1 好的,我有一些进展,我现在创建了表,但没有数据。问题是我不应该使用模拟存储库。我必须将上下文 XML 更新为以下内容。所以下一个问题是尝试找出为什么它没有用数据填充我新创建的表
编辑 2 JpaTransactionManager bean 和 tx 注释驱动已添加到上下文中
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">
<context:property-placeholder location="file:src/main/webapp/WEB-INF/config/application-test.properties"
ignore-resource-not-found="false" />
<jpa:repositories base-package="com.tvfreakz.repository" />
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="punit"/>
<property name="dataSource" ref="dataSource"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true"/>
</bean>
</property>
<property name="jpaPropertyMap">
<map>
<entry key="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect"/>
<entry key="hibernate.hbm2ddl.auto" value="update"/>
<entry key="hibernate.format_sql" value="true"/>
<entry key="hibernate.show_sql" value="true"/>
</map>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="dataSource" class="com.jolbox.bonecp.BoneCPDataSource">
<property name="driverClass" value="${db.driver}" />
<property name="jdbcUrl" value="${db.url}" />
<property name="username" value="${db.username}" />
<property name="password" value="${db.password}" />
</bean>
</beans>
编辑 3 好的,在我的 Maven 依赖项中包含 slf4j 并创建一个设置了 DEBUG 级别的 log4j.properties 文件后,我设法启用了 DEBUG 级别。
我在日志中看到了这个,这也许提供了线索?
14:47:05,670 INFO TestContextManager:242 - Could not instantiate TestExecutionListener [com.github.springtestdbunit.DbUnitTestExecutionListener]. Specify custom listener classes or make the default listener classes (and their required dependencies) available. Offending class: [org/dbunit/dataset/IDataSet]
我相信这是参考了我的这部分测试代码
@TestExecutionListeners({ DependencyInjectionTestExecutionListener.class,
DirtiesContextTestExecutionListener.class,
TransactionalTestExecutionListener.class,
DbUnitTestExecutionListener.class })
随着我对原始 post 所做的编辑,我似乎在我的 Maven pom.xml 中缺少 DBUnit 依赖项。添加以下内容后,我现在有了数据,谢谢 Petri 和 Phil 的帮助!
<dependency>
<groupId>org.dbunit</groupId>
<artifactId>dbunit</artifactId>
<version>2.5.0</version>
</dependency>
我一直在关注 Petri Kainulainen 的 this 非常有用的博客 post,使用 spring-data-jpa 和 DBUnit 为我的 Spring 存储库代码编写集成测试.
我的 bean 上下文 XML 是这样设置的
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">
<context:property-placeholder location="file:src/main/webapp/WEB-INF/config/application-test.properties"
ignore-resource-not-found="false" />
<bean id="dataSource" class="com.jolbox.bonecp.BoneCPDataSource">
<property name="driverClass" value="${db.driver}" />
<property name="jdbcUrl" value="${db.url}" />
<property name="username" value="${db.username}" />
<property name="password" value="${db.password}" />
</bean>
<bean id="directorRepository" name="directorRepositoryMock" class="org.mockito.Mockito"
factory-method="mock">
<constructor-arg value="com.tvfreakz.repository.DirectorRepository" />
</bean>
</beans>
我的数据集 XML 具有以下内容
<!DOCTYPE dataset SYSTEM "my-dataset.dtd">
<dataset>
<director directorid="1" director="Ridley Scott" />
<director directorid="2" director="James Cameron" />
<director directorid="3" director="David Fincher" />
<director directorid="4" director="Jean-Pierre Jeunet" />
</dataset>
这是存储库界面
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.tvfreakz.model.entity.Director;
@Repository("directorRepository")
public interface DirectorRepository extends JpaRepository<Director, Long> {
Director findByDirectorId(Long directorId);
}
我的测试class是这样设置的
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertEquals;
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.support.DirtiesContextTestExecutionListener;
import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
import com.github.springtestdbunit.DbUnitTestExecutionListener;
import com.github.springtestdbunit.annotation.DatabaseSetup;
import com.tvfreakz.model.entity.Director;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"file:src/main/webapp/WEB-INF/config/testMVCContext.xml"})
@TestExecutionListeners({ DependencyInjectionTestExecutionListener.class,
DirtiesContextTestExecutionListener.class,
TransactionalTestExecutionListener.class,
DbUnitTestExecutionListener.class })
@DatabaseSetup("testDataset.xml")
public class ITDirectorRepositoryTest {
@Autowired
private DirectorRepository repository;
@Test
public void testFindByDirectorIdWhenNoDirectorFound() {
Director director = repository.findByDirectorId(10L);
assertNull(director);
}
@Test
public void testFindByDirectorIdWhendirectorIsFound() {
Director director = repository.findByDirectorId(1L);
assertEquals("Ridley Scott", director.getDirectorName());
}
}
我期待 @DatabaseSetup
注释采用我的配置并将所有表和数据插入设置到由 dataSource
bean 配置的测试数据库中。
这似乎什么都不做(即数据库保持空白,没有表或数据),我的第二个测试 testFindByDirectorIdWhendirectorIsFound
失败,因为返回的 director 为空。我错过了什么?
编辑 1 好的,我有一些进展,我现在创建了表,但没有数据。问题是我不应该使用模拟存储库。我必须将上下文 XML 更新为以下内容。所以下一个问题是尝试找出为什么它没有用数据填充我新创建的表
编辑 2 JpaTransactionManager bean 和 tx 注释驱动已添加到上下文中
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">
<context:property-placeholder location="file:src/main/webapp/WEB-INF/config/application-test.properties"
ignore-resource-not-found="false" />
<jpa:repositories base-package="com.tvfreakz.repository" />
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="punit"/>
<property name="dataSource" ref="dataSource"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true"/>
</bean>
</property>
<property name="jpaPropertyMap">
<map>
<entry key="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect"/>
<entry key="hibernate.hbm2ddl.auto" value="update"/>
<entry key="hibernate.format_sql" value="true"/>
<entry key="hibernate.show_sql" value="true"/>
</map>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="dataSource" class="com.jolbox.bonecp.BoneCPDataSource">
<property name="driverClass" value="${db.driver}" />
<property name="jdbcUrl" value="${db.url}" />
<property name="username" value="${db.username}" />
<property name="password" value="${db.password}" />
</bean>
</beans>
编辑 3 好的,在我的 Maven 依赖项中包含 slf4j 并创建一个设置了 DEBUG 级别的 log4j.properties 文件后,我设法启用了 DEBUG 级别。
我在日志中看到了这个,这也许提供了线索?
14:47:05,670 INFO TestContextManager:242 - Could not instantiate TestExecutionListener [com.github.springtestdbunit.DbUnitTestExecutionListener]. Specify custom listener classes or make the default listener classes (and their required dependencies) available. Offending class: [org/dbunit/dataset/IDataSet]
我相信这是参考了我的这部分测试代码
@TestExecutionListeners({ DependencyInjectionTestExecutionListener.class,
DirtiesContextTestExecutionListener.class,
TransactionalTestExecutionListener.class,
DbUnitTestExecutionListener.class })
随着我对原始 post 所做的编辑,我似乎在我的 Maven pom.xml 中缺少 DBUnit 依赖项。添加以下内容后,我现在有了数据,谢谢 Petri 和 Phil 的帮助!
<dependency>
<groupId>org.dbunit</groupId>
<artifactId>dbunit</artifactId>
<version>2.5.0</version>
</dependency>