簡體   English   中英

PowerMock與EasyMock,期望返回null而不是模擬

[英]PowerMock with EasyMock, expectation returns null instead of a mock

尋找有關為何期望返回null而不是請求的模擬的指導。 有問題的模擬是“未來”,並且遵循與正確返回的其他模擬相同的模式。

為了向具有powermock和easymock經驗的人提供所有信息,我提供了所有代碼,包括受測代碼和設置模擬和行為的測試代碼。 有問題的期望是

EasyMock.expect( mockAsyncClient.execute( EasyMock.isA( HttpGet.class ),
EasyMOck.isA( HttpClientContext.class ), isNull() ).andReturn( mockFuture )

它產生一個null而不是返回一個模擬的Future。

任何想法,將不勝感激。

ps有很多模擬安裝程序需要測試此功能,我希望這不會妨礙評估問題。 任何刪除不必要的模擬基礎設施的建議將不勝感激。

這是測試中的代碼

    public <T> T getResponse( ResponseHandler<T> responseHandler )
    throws IOException, InterruptedException, ExecutionException
{
    String connectTo = buildUri();

    try( CloseableHttpAsyncClient httpClient =
                                             HttpAsyncClients.custom()
                                                             .setConnectionManager( connManager )
                                                             .build() ) {
        HttpGet request = new HttpGet( connectTo );
        HttpClientContext ctx = HttpClientContext.create();

        addHeaders( request );

        httpClient.start();

        Future<HttpResponse> futureResponse = httpClient.execute( request, ctx, null ); //<-- this line executes using a verified HttpClient mock but returns null

        HttpResponse response = futureResponse.get();

        return responseHandler.handleResponse( response );
    }
}

測試代碼:

    @Test
@PrepareOnlyThisForTest( { HttpAsyncClients.class, HttpAsyncClientBuilder.class } )
public void testGetResponseCallsResponseHandler()
    throws IOException, InterruptedException, ExecutionException
{
    // create mocks to be used when exercising the code under test
    CloseableHttpAsyncClient mockAsyncClient =
                                             EasyMock.createMock( CloseableHttpAsyncClient.class );

    PowerMock.mockStatic( HttpAsyncClients.class );

    HttpAsyncClientBuilder mockClientBuilder =
                                             PowerMock.createMock( HttpAsyncClientBuilder.class );
    HttpAsyncClientBuilder mockClientBuilder2 =
                                              PowerMock.createMock( HttpAsyncClientBuilder.class );

    HttpResponse mockResponse = PowerMock.createMock( HttpResponse.class );
    StatusLine mockStatusLine = PowerMock.createMock( StatusLine.class );
    @SuppressWarnings( "unchecked" )
    Future<HttpResponse> mockFuture = PowerMock.createMock( Future.class );

    // set up expectations that use the mocks
    EasyMock.expect( HttpAsyncClients.custom() ).andReturn( mockClientBuilder );
    EasyMock.expect( mockClientBuilder.setConnectionManager( EasyMock.isA( NHttpClientConnectionManager.class ) ) )
            .andReturn( mockClientBuilder2 );
    EasyMock.expect( mockClientBuilder2.build() ).andReturn( mockAsyncClient );

    mockAsyncClient.start();
    EasyMock.expectLastCall().once();

    EasyMock.expect( mockAsyncClient.execute( EasyMock.isA( HttpGet.class ),
                                              EasyMock.isA( HttpClientContext.class ),
                                              EasyMock.isNull() ) )
            .andReturn( mockFuture );

    EasyMock.expect( mockFuture.get() ).andReturn( mockResponse );

    EasyMock.expect( mockResponse.getStatusLine() ).andReturn( mockStatusLine );
    EasyMock.expect( mockStatusLine.getStatusCode() ).andReturn( 200 );

    mockAsyncClient.close();
    EasyMock.expectLastCall().once();

    PowerMock.replayAll();

    ClientConfig cfg = new ClientConfigBuilder().build();
    RestClient client = new RestClient( cfg );

    int statusCode = client.getResponse( new ResponseHandler<Integer>() {

        @Override
        public Integer handleResponse( HttpResponse response )
            throws ClientProtocolException, IOException
        {
            StatusLine statusLine = response.getStatusLine();
            return statusLine.getStatusCode();
        }

    } );

    PowerMock.verifyAll();

    assertEquals( "status code incorrect", 200, statusCode );
}

我發現了問題,並且這是我確定已經遇到許多其他問題的問題之一...

我錯誤地使用EasyMock而不是PowerMock創建模擬的事實可以解釋返回空值的模擬:

CloseableHttpAsyncClient mockAsyncClient =
                                         EasyMock.createMock( CloseableHttpAsyncClient.class );

通過將該行更改為

CloseableHttpAsyncClient mockAsyncClient =
                                         PowerMock.createMock( CloseableHttpAsyncClient.class );

測試通過了。

原因是PowerMock擁有用於創建的模擬,並且只能驗證這些模擬的行為。 PowerMock包裝了EasyMock,因此需要對受控對象進行可視化。

對於受此問題影響的人,請對問題進行投票。 不知道為什么我不贊成投票,但請使這個答案更容易發現。

謝謝,羅賓。

我在這里總結,因為我試圖在類似這樣的類上使用whenNew(SomeClass.class).withAnyArguments()

class SomeClass {
     public SomeClass(String... args) { }
}

原來withAnyArguments()與varargs不匹配。 就我而言,解決方法是:

whenNew(SomeClass.class).withArguments(Matchers.<String>anyVararg()).thenReturn(myMock);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM