多个包装对象中的反射



在一个JUnit测试中,我想更改Spring DAO中的hibernate模板。这个DAO是

  1. 用@Transactional注释,所以它在运行时被包装,
  2. 被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");
    }
}

一些警告,如果可能的话,避免部分嘲弄(使用间谍)。避免使用你不拥有的类型,你应该阅读这篇博客文章,为什么这是一个坏主意。

相关内容

  • 没有找到相关文章

最新更新