2016-09-19 198 views
2

我試圖使用JUnit,的Mockito和PowerMock創建單元測試我試圖使用JUnit,的Mockito和PowerMock創建單元測試

我的問題是,我在嘗試的一個類模擬返回一個空對象

這是我的代碼

@RunWith(PowerMockRunner.class) 
@PrepareForTest(ClientBuilder.class) 
public class SolrPopulateApplicationTest { 

    @Mock 
    ClientConfig clientConfig; 

    @Mock 
    Client client; 

    @Mock 
    Response response; 

    @Mock 
    JerseyClient jerseyClient; 

    @Mock (answer = Answers.RETURNS_DEEP_STUBS) 
    JerseyWebTarget jerseyWebTarget; 

    @InjectMocks 
    @Autowired 
    SolrPopulateApplication solrPopulateApplication; 

    @Test 
    public void indexTest(){ 

     PowerMockito.mockStatic(ClientBuilder.class); 

     ClientBuilder cli = Mockito.mock(ClientBuilder.class); 

    when(ClientBuilder.newClient(Matchers.any())).thenReturn(client); 

     when(jerseyClient.target(Matchers.anyString())).thenReturn(jerseyWebTarget); 

     when(jerseyWebTarget.path(Matchers.anyString()) 
       .queryParam(Matchers.anyString(),Matchers.anyString()) 
     .request(Matchers.anyString()) 
       .header(Matchers.anyString(),Matchers.anyString()) 
     .post(Matchers.any())).thenReturn(response); 

     boolean var = solrPopulateApplication.index("test","test"); 

    } 
} 

當調試斷點被放置在所有的嘲笑應該已經設置我得到以下

client = {[email protected]} "client" 
response = {[email protected]} "response" 
jerseyWebTarget = {[email protected]} "null" 
solrPopulateApplication = {[email protected]} 
jerseyClient = {[email protected]} "jerseyClient" 
cli = {[email protected]} "Mock for ClientBuilder, hashCode: 2080643905" 
this = {[email protected]} 

正如你所看到的jerseyWebClient是一個NULL,這導致nullpointerexception當我嘗試運行測試。

我試圖從@mock語句中刪除(answer = Answers.RETURNS_DEEP_STUBS),這沒有什麼區別。

被測試的方法實際上調用了實現JerseyWebTarget類的接口。我已經確定我試圖通過在JerseyWebTarget類中放置一個調試器來確保它停止在通過接口調用的方法上來模擬正確的類。

誰能告訴我爲什麼會發生這種情況,以及如何解決這個問題。

+0

您還應該包含您的導入語句,以便您的示例已完成。我對PowerMock並不熟悉,並且據我所知,PowerMock和Mockito都可以包含模擬註釋。 – tonicsoft

回答

1

假設你正在使用的Mockito @Mock註釋...

要使用的Mockito @Mock註解,你必須每次測試之前執行一個特定的代碼行。您可以在設置方法做到這一點:

@Before 
public void init() { 
    MockitoAnnotations.initMocks(this); 
} 

你還必須@RunWith(MockitoJUnitRunner.class)但由於您使用的是PowerMockRunner那麼這可能不是必要的。

我會建議你儘可能避免使用PowerMock,或者至少在使用PowerMock編寫測試之前讓你的模擬與Mockito一起工作。我從PowerMock wiki引用以下內容:

請注意,PowerMock主要用於具有單元測試專業知識的人員。把它交給初級開發者可能會造成更多的傷害而不是好事。

除非在這裏需要PowerMock的一個非常具體的原因,否則避免它。例如,您可以將JerseyWebTarget傳遞到您的SolrPopulateApplication的構造函數中,而不是直接調用您正在測試的課程中的ClientBuilder

此外,PowerMock和Mockito可能不會總是在一起玩。例如,請參見this bug

+0

被嘲笑的方法之一是靜態的 是模擬靜態方法所需的powermock嗎? – lee

+0

PowerMock是模擬靜態方法所必需的。我建議你應該避免嘲笑靜態方法。相反,將靜態方法調用包裝在您創建的對象的實例方法中。這個實例方法現在可以在沒有PowerMock的情況下被模擬。更好的是,不要在正在測試的類中調用方法 - 將方法的結果傳遞給類構造函數。 – tonicsoft