多个包装对象的反射

时间:2011-11-04 10:08:49

标签: java reflection junit mockito transactional

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

  1. 使用@Transactional进行注释,以便在运行时和
  2. 中进行包装
  3. Mockitos间谍() - 方法。所以DAO将被那个间谍第二次包裹。
  4. 所以DAO现在有两个包装对象:一个来自@Transactional,一个来自间谍。由于不知道首先创建了哪个包装器这一事实,我无法通过反射在DAO中设置休眠模板。

    如何在双重包裹的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
    }
    }
    

2 个答案:

答案 0 :(得分:2)

调用setter方法而不是访问该字段。

答案 1 :(得分:2)

看来你的反射代码是错误的。请改用此语句:

field.set(daoSpy, mySpecialMockedTemplate);

然而,查看您的测试代码,您似乎正在使用Spring创建MyDao实例。使用反射设置模板似乎有点奇怪,为什么不在Spring中配置它? 甚至使用实际的二传手?或者保护字段,因此只有单元测试才能访问它。

编辑:关于注入,您可以在测试中创建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");
    }
}

虽然有一些警告,但如果可能的话,避免部分嘲笑(使用间谍)。避免使用你不拥有的类型,你应该阅读这个blog post entry为什么这是一个坏主意。