2011-11-04 54 views
0

在JUnit测试中,我想更改Spring DAO中的hibernate模板。这是DAO多个包装对象中的反射

  1. 注释有@Transactional所以它被运行时期间包裹和
  2. 由Mockitos间谍()spyed时 - 方法。所以DAO将被该间谍第二次包装。

所以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 
} 
} 
+0

嗨,你可以添加一些示例代码? – Brice

回答

2

呼叫setter方法而不是访问字段。

+0

使用setter并不能解决问题:由于@Autowired,Spring会对dao进行包装。二传手将设置任何给定的属性,而不是道。 – Steven

2

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

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"); 
    } 
} 

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

+0

PowerMockito可能对此有所帮助,还有一个选择。 – AHungerArtist

+0

尽管PowerMock lib适用于难以测试的代码,但我强烈建议避免需要Powermock进行测试的设计代码。这是黑客和代码/测试难以维护的道路。 – Brice

+0

对,我发了一个错误的反射代码。使用setter并不能解决问题:由于@Autowired,Spring会对dao进行包装。二传手将设置任何给定的属性,而不是道。实际上在Spring中配置似乎是唯一的方法。另外,道可以实现自动化,而不是自动装配。 – Steven