2013-11-01 81 views
6

mockito確實不能模擬CGLIB已經增強的對象嗎?模擬CGLIB增強對象

public class Article { 

    @Autowired 
    private dbRequestHandler 

    @Autowired 
    private filesystemRequestHandler 

    @Transactional 
    public ArticleDTO getArticleContents() { 

     //extractText() and then save the data in DTO 
     //extractImages() and then save the data in DTO 
     // some other calls to other databases to save data in dto 

     return articleDTO; 

    } 
    public void extractText() { 

     //call to DB 

    } 

    public void extractImages() { 

     // call to file system 

    } 
} 


public class IntegrationTest { 

    @Autowired 
    private Article article; 

    //setup method { 

    articleMock = Mockito.spy(article); 

    doNothing().when(articleMock).extractImages(); 
} 
} 

在上面的例子中,當涉及到doNothing().when(articleMock).extractImages();它實際上調用了真正的函數。仔細看看articleMock得到了兩次增強。 autowiring的一個原因和spying的第二次原因。

如果我不能窺探enhaced對象,那麼我如何在我的集成測試中測試getArticle()方法,以便我可以驗證是否返回了正確的DTO。

注:我其實不想測試文件系統調用的方法。只是數據庫的。那就是爲什麼我需要測試getArticle方法。

+0

以下是我發現的[文檔](http://docs.mockito.googlecode.com/hg/latest/org/mockito/Mockito.html#doNothing())我不模仿地看到問題。你是否嘗試過自己創建'Article',而不是自動裝配(或者至少在自動裝配後驗證了正確性)? – atomman

+0

是的,如果我自己創造「文章」,我可以窺探。但我必須自動裝載它,因爲在我的應用程序中,每個對象都是通過自動裝配創建的,如果我自己啓動「Article」,則Article類中的字段爲空(例如,reqHandler對象)。如果我也啓動這些字段,那麼這些類中的字段爲空,鏈接繼續。 – samach

+0

過濾的代碼和您的問題不適合 - getArticle()有問題,getArticleContents()在代碼中 - 它造成了一些混淆。你應該考慮提供更多的'IntegrationTest'代碼。 – Cebence

回答

3

如果我理解正確,你的班級由Spring連線。只有在沒有接口的情況下,Spring纔會使用CGLIB來確保事務行爲,這是由對象實現的。如果有一個接口,它使用簡單的JDK動態代理。 (請參閱http://docs.spring.io/spring/docs/3.0.0.M3/reference/html/ch08s06.html

也許你可以嘗試提取接口,並讓Spring使用動態代理。也許那麼Mockito可以表現得更好。

1

如果您作爲真正的單元測試運行,而不是作爲集成測試運行,則不需要在具有Spring自動裝載的容器中運行。在你的一個評論中,我想你提到了這個,你注意到有一連串的鏈接對象引用,你也必須提供。但是有一種解決方法。 Mockito提供了一些預定義的Answer類,您可以使用它們初始化您的模擬。你可能想看看RETURNS_DEEP_STUBS,這可能會讓你解決這個問題。

1

請問您是否需要使用隨時可編譯的代碼更新您的問題。下面是一些代碼審查建議:

這個問題的代碼問題:

  • Article.java缺少導入:org.springframework.beans.factory.annotation.Autowired
  • Article.java缺少的import: org.springframework.transaction.annotation.Transactional
  • Article.java屬性語法問題:dbRequestHandler
  • Article.java屬性語法問題:filesystemRequestHandler
  • Article.java方法沒有初始化return語句:articleDTO

這裏是你,你有固定的上述問題questionCode也許應該使用什麼:

Article.java

import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.transaction.annotation.Transactional; 

public class Article { 

    @Autowired 
    private Object dbRequestHandler; 

    @Autowired 
    private Object filesystemRequestHandler; 

    @Transactional 
    public ArticleDTO getArticleContents() { 

     // extractText() and then save the data in DTO 
     // extractImages() and then save the data in DTO 
     // some other calls to other databases to save data in dto 

     ArticleDTO articleDTO = null; 
     return articleDTO; 

    } 

    public void extractText() { 

     // call to DB 

    } 

    public void extractImages() { 

     // call to file system 

    } 
} 

IntegrationTest.java是testClass的一個不好名稱,因爲它是通用的。我會建議ArticleTest進行java單元測試。

ArticleTest.java

import org.junit.Assert; 
import org.junit.Test; 
import org.junit.runner.RunWith; 
import org.mockito.InjectMocks; 
import org.mockito.Mock; 
import org.mockito.Mockito; 
import org.powermock.core.classloader.annotations.PrepareForTest; 
import org.powermock.modules.junit4.PowerMockRunner; 
import org.springframework.beans.factory.annotation.Autowired; 

@RunWith(PowerMockRunner.class) 
@PrepareForTest(ClassWithPrivate.class) 
public class ArticleTest { 

    @InjectMocks 
    private Article cut; 

    @Mock 
    private Object dbRequestHandler; 

    @Mock 
    private Object filesystemRequestHandler; 

    @Test 
    public void testeExtractImages() { 

     /* Initialization */ 
     Article articleMock = Mockito.spy(cut); 

     /* Mock Setup */ 
     Mockito.doNothing().when(articleMock).extractImages(); 

     /* Test Method */ 
     ArticleDTO result = cut.getArticleContents(); 

     /* Asserts */ 
     Assert.assertNull(result); 

    } 

} 
0

您可以利用AdditionalAnswers.delegatesTo方法。在下面的例子中,secondProxyDoingMocking聲明創建了一個類似於間諜的東西(與實現spy()方法比較),除了它使用「輕量級」方法委派。

import org.mockito.AdditionalAnswers; 

public class ArticleTest { 

    @Autowired 
    private Article firstProxyDoingAutowiring; 

    @Test 
    public void testExtractImages() { 
     Article secondProxyDoingMocking = Mockito.mock(Article.class, 
       Mockito.withSettings().defaultAnswer(
         AdditionalAnswers.delegatesTo(firstProxyDoingAutowiring) 
       ) 
     ); 
     Mockito.doNothing().when(secondProxyDoingMocking).extractImages(); 
     ... 
    } 

} 

我沒有測試這個例子,但我從我的工作代碼組裝它。我的用例類似:爲給定方法返回常量值,爲Spring的所有其他方法調用真實方法 - 註釋bean。