2011-11-04 40 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