在一个JUnit测试中,我想更改Spring DAO中的hibernate模板。这个DAO是
- 用@Transactional注释,所以它在运行时被包装,
- 被Mockitos spy()-方法监视。所以DAO将被间谍第二次包裹。
所以DAO现在有两个包装对象:一个来自@Transactional,一个来自spy。由于不知道首先创建了哪个包装器,因此我无法通过反射在DAO中设置hibernate模板。
如何在双包装DAO中设置模板?
[编辑]一些来源:/**
* This class gets wrapped by a proxy object because of @Transactional.
*/
@Transactional
public class MyDao implements SomeDaoInterface { ... }
在测试类中:
public class MyTestClass {
@Autowired
private MyDao myDao;
@Test
public void myTestMethod() throws Exception {
final MyDao daoSpy = spy(myDao); // Dao gets wrapped with second wrapper
final Field field = MyDao.class.getDeclaredField("template");
field.setAccessible(true);
field.set(daoSpy, mySpecialMockedTemplate); // ERROR: want to inject the template but
// dont know in which wrapper
}
}
调用setter方法而不是访问字段。
看来你的反射代码是错误的。请使用下面的语句:
field.set(daoSpy, mySpecialMockedTemplate);
然而,看看你的测试代码,似乎你正在使用Spring创建MyDao
实例。使用反射来设置模板似乎有点奇怪,为什么不在Spring中配置它呢?或者甚至使用实际的setter ?或者使该字段受保护,这样只有单元测试可以访问它。
编辑:关于注入,您可以在测试中创建DAO实例,并通过Mockito注入specialMockedTemplate
。你可以这样写:
@RunWith(MockitoJUnitRunner.class)
public class MyTestClass {
@InjectMocks private MyDao dao;
@Mock SpecialTemplate specialTemplate;
@Test void dao_should_call_the_template_with_parameter_A_and_B() {
// given
// when
dao.someCall("A", "B");
// then
verify(specialTemplate).someCallWith("A", "B");
}
}
一些警告,如果可能的话,避免部分嘲弄(使用间谍)。避免使用你不拥有的类型,你应该阅读这篇博客文章,为什么这是一个坏主意。