2013-03-13 128 views
1

我想單元測試我的類,並模擬DAO提供可預測的結果。不過,看起來我的DAO方法仍然被調用,因爲我收到一個休眠錯誤。單元測試模擬注入

org.hibernate.exception.GenericJDBCException:找不到站點TST。

這個錯誤是我的數據庫不包含TST的結果,但不應該因爲我嘲笑DAO而被調用?我如何嘲笑這個調用,以至於數據庫沒有被擊中。

下面是我如何設置我的模擬

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations = { "classpath:applicationContext.xml" }) 
public class MyServiceTest{ 

    @Autowired 
    private MyService service; 

    private MyDAO dao; 

    private LinkedList objs;  


    @Before 
    public void init() throws SecurityException, NoSuchFieldException, 
      IllegalArgumentException, IllegalAccessException { 


     // mock the dao for predictable results 
     dao = mock(MyDAO.class); 

     when(dao.myDBCall(anyString(), any(Date.class))).thenReturn(legs); 
     Field f = MyService.class.getDeclaredField("dao"); 
     f.setAccessible(true); 
     f.set(service, dao); 


    } 

    @Test 
    public void testCall() { 
     // construct our sample leg data 
     legs = new LinkedList(); 
//fill in my stub data i want to return 

     Collections.shuffle(legs); 

     List results = service.testingCall("TST", new Date()); // this fails because service is using the dao, but it is making a call to the DB with this garbage 'Test' param rather than just returning 'legs' as stated in my when clause 
     assertThat(results, not(nullValue())); 


    } 

    @Test 
    public void testGetGates() { 
     // fail("Not yet implemented"); 
    } 

    @Test 
    public void testGetStations() { 
     // fail("Not yet implemented"); 
    } 
} 

回答

1

爲先,而不是Field f = MyService.class.getDeclaredField("dao");檢查PowerMock(檢查Whitebox

嘲弄一個對象不會阻止休眠啓動(因爲你正在加載applicationContext.xml,所以休眠會嘗試連接到數據庫)。你的模擬 - 它只是一個測試實例的一個字段的POJO,而不是Spring bean或類的替代品。如果你只想測試dao和服務類(創建清晰的單元測試) - 從測試中刪除與Spring相關的註釋並自行完成(創建模擬,創建服務,將模擬服務和測試)。

如果您想用Spring上下文測試您的應用程序(創建集成測試) - 創建H2 in-memory database進行休眠並測試您的服務(不要忘記在@After中清除它)。

第三條道路 - 分割你的配置文件到兩個彈簧的配置文件(例如devtest)和實施嘲笑自己(把模擬到test,真正的Hibernate和DAO來dev)。

如果你不想使用Spring配置文件 - 可以將applicationContext.xml分爲3個文件(對於普通的bean,對於真正的DB beans,對於mock)。

而且一個更性感的方式 - 使用springockito-annotations(但你仍然需要避免休眠加載)

+0

不幸的是H2不是一個選項。至於「自己做」,我的服務還有許多其他的bean需要自動注入,這使得這種方法不切合實際。真的沒有辦法完全嘲弄道? – 75inchpianist 2013-03-13 22:46:29

+0

你可以。首先,將你的hibernate相關的xml配置移到一些(「dev」)Spring配置文件(谷歌的「spring配置文件」)。然後創建dao的存根(模擬)實現並將其放到「測試」配置文件中。在測試中添加@ActiveProfiles(「test」)註釋之後(您還需要在常規應用程序啓動時激活「dev」配置文件)。如果你不喜歡配置文件 - 在3個文件(applicationContext.xml,dev.xml,mock.xml)中拆分配置 – 2013-03-13 22:56:25

+0

並且還檢查 - https://bitbucket.org/kubek2k/springockito/wiki/Home – 2013-03-13 22:59:01

2

我認爲你Service被彈簧實例與Daoapplication-context.xml定義,你會得到你的錯誤之前,你甚至嘗試在你的服務以注入模擬。

我喜歡用來測試我的服務的一件事是一個Autowired構造函數,然後在我的測試中,我沒有通過spring實例化我的服務,但使用構造函數和模擬。

private MyDao myDao; 

@Autowired 
public MyService(MyDao myDao){ 
this.myDao = myDao; 
} 

然後在您的測試:

MyService myService = new Myservice(mockedDao); 
+0

錯誤肯定來後我注入我的模擬。我可以通過逐步調試器來判斷 – 75inchpianist 2013-03-13 22:41:38

+0

您的服務是否包含其他人dao? – benzonico 2013-03-13 22:43:23

+0

不只是一個,但它確實包含我需要的其他bean AutoInjected – 75inchpianist 2013-03-13 22:45:33