Java 多个包裹对象中的反射
在JUnit测试中,我想更改SpringDAO中的hibernate模板。这把刀是Java 多个包裹对象中的反射,java,reflection,junit,mockito,transactional,Java,Reflection,Junit,Mockito,Transactional,在JUnit测试中,我想更改SpringDAO中的hibernate模板。这把刀是 使用@Transactional进行注释,以便在运行时和 被Mockitos spy()方法监视。所以刀会被那个间谍第二次包起来 因此DAO现在有两个包装对象:一个来自@Transactional,一个来自spy。由于不知道哪些包装器是首先创建的,因此我无法通过反射在DAO中设置hibernate模板 如何在双包装DAO中设置模板 [编辑] 一些资料来源: /** * This class gets wrappe
/**
* 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方法,而不是访问字段 调用setter方法,而不是访问字段 看来您的反射代码是错误的。请使用以下语句:
field.set(daoSpy, mySpecialMockedTemplate);
然而,看看您的测试代码,您似乎正在使用Spring创建MyDao
实例。使用反射来设置模板似乎有点奇怪,为什么不在Spring中配置它呢?
或者甚至使用一个实际的setter?或者使字段受保护,这样只有单元测试才能访问它
编辑:关于注入,您可以在测试中创建DAO实例,并让Mockito注入您的SpecialLockedTemplate
。你可以这样写:
@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");
}
}
不过有一些警告,如果可能的话,避免部分嘲弄(使用间谍)。避免使用你不拥有的类型,你应该阅读这篇文章,为什么这是一个坏主意。看来你的反射代码是错误的。请使用以下语句:
field.set(daoSpy, mySpecialMockedTemplate);
然而,看看您的测试代码,您似乎正在使用Spring创建MyDao
实例。使用反射来设置模板似乎有点奇怪,为什么不在Spring中配置它呢?
或者甚至使用一个实际的setter?或者使字段受保护,这样只有单元测试才能访问它
编辑:关于注入,您可以在测试中创建DAO实例,并让Mockito注入您的SpecialLockedTemplate
。你可以这样写:
@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");
}
}
不过有一些警告,如果可能的话,避免部分嘲弄(使用间谍)。避免使用您不拥有的类型,您应该阅读这篇文章,为什么这是一个坏主意。Hi,您可以添加一些示例代码吗?Hi,您可以添加一些示例代码吗?PowerMockito在这里可能会有所帮助,还有一个选项。虽然PowerMock库对于难以测试的代码非常有用,我强烈建议避免使用需要测试Powermock的设计代码。这是一条黑客之路,代码/测试很难维护。对,我发布了一个错误的反射代码。使用setter并不能解决问题:Spring因为@Autowired而对dao进行包装。setter将把任何给定的属性设置到这个包装中,而不是dao。在Spring中进行配置实际上似乎是实现这一点的唯一方法。或者,dao可以被实例化而不是自动连接。Mockito提供了一个轻型自动注入实用程序,我编辑了这方面的答案。PowerMockito在这里可能会有所帮助,因为还有另一个选项。虽然PowerMock库对于难以测试的代码非常有用,但我强烈建议避免需要测试PowerMock的设计代码。这是一条黑客之路,代码/测试很难维护。对,我发布了一个错误的反射代码。使用setter并不能解决问题:Spring因为@Autowired而对dao进行包装。setter将把任何给定的属性设置到这个包装中,而不是dao。在Spring中进行配置实际上似乎是实现这一点的唯一方法。或者dao可以被实例化而不是自动连接。Mockito提供了一个轻型自动注入实用程序,我在这方面编辑了我的答案。使用setter并不能解决问题:Spring因为@autowired而包装dao。setter会将任何给定的属性设置到此包装中,而不是dao。使用setter并不能解决问题:Spring会因为@Autowired而包装dao。setter将把任何给定的属性设置到这个包装中,而不是dao。