我正在尝试测试Spring @Repository
组件,但首先我必须注入表名以使其正常工作。
这是我做的。这是一个简单的DAO:
@Repository
@Transactional
public class AccountDAO {
@Autowired
private JdbcTemplate jdbcTemplate;
private String table = "accounts"; <-- I need to inject this value from tests
...
}
单元测试:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:spring-web-servlet.xml")
@Transactional
public class AccountDaoTest {
@Autowired
private AccountDAO accountDAO;
@Before
public void init() {
accountDAO = Mockito.spy(accountDAO);
ReflectionTestUtils.setField(accountDAO, "table", "accounts_test");
}
...
}
问题是ReflectionTestUtils
忽略了字段赋值,accountDAO
仍然使用accounts
表名值而不是accounts_test
。
如何四舍五入?
您可以使用两种技术来更改存储在私有变量中的表名:
-
ReflectionTestUtils
没有mockit间谍。 - 使用Mockito的注解@Spy和@InjectMocks
但是这不是非常可靠的集成测试,因为当有人更改table
模式时,您的测试将无法捕获问题。有很多方法可以解决这个问题:
- 如果您的应用程序执行增量脚本将DB模式和元数据迁移到最新版本(例如通过使用Liquibase或FlyWay),您可以在测试期间在内存/嵌入式数据库(例如H2, HSQL)中重新创建DB模式,并对原始表运行测试。这是现代的方法。
- 如果你的公司架构是老式的,其中一些dba在你的应用程序部署上独立执行SQL增量脚本,那么必须有一些DEV DB环境。使用该环境进行集成测试。你可以提前整理/准备表格进行测试。
在这里,您想要分离真实数据库和集成测试数据库。您的目标是测试DAO层是否工作良好。我建议完全删除Mockito并使用DBUnit。
然后,保留DAO、Spring和JUnit。没有必要注入另一个表名。
DBUnit允许您创建一个小型数据库,仅用于根据XML数据集进行测试。
像这样:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {PersistenceContext.class})
@TestExecutionListeners({ DependencyInjectionTestExecutionListener.class,
DirtiesContextTestExecutionListener.class,
TransactionalTestExecutionListener.class,
DbUnitTestExecutionListener.class })
@DatabaseSetup("my-dbunit-dataset.xml")
public class AccountDAOTest {
@Autowired
private AccountDAO accountDAO;
@Test
public void findAllAccounts() {
assertThat(accountDAO.findAll().size(), is(2));
}
}
my-dbunit-dataset.xml:
<dataset>
<account id="1" value1="foo" />
<account id="2" value1="bar" />
</dataset>
DBunit真的很强大。你可以在这里找到官方链接:
http://dbunit.sourceforge.net/howto.htmlDbUnit -入门
您还可以为table
字段定义setter方法:
protected void setTable(String pTableName)
this.table = pTableName;
}
并在测试类before()
方法中调用setter