JUnit&Mockito:如何将字段值注入到Spring组件?



我正在尝试测试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

如何四舍五入?

您可以使用两种技术来更改存储在私有变量中的表名:

  1. ReflectionTestUtils没有mockit间谍。
  2. 使用Mockito的注解@Spy和@InjectMocks

但是这不是非常可靠的集成测试,因为当有人更改table模式时,您的测试将无法捕获问题。有很多方法可以解决这个问题:

  1. 如果您的应用程序执行增量脚本将DB模式和元数据迁移到最新版本(例如通过使用Liquibase或FlyWay),您可以在测试期间在内存/嵌入式数据库(例如H2, HSQL)中重新创建DB模式,并对原始表运行测试。这是现代的方法。
  2. 如果你的公司架构是老式的,其中一些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

最新更新