使用EasyMock的PowerMock,期望返回null而不是模拟

时间:2017-09-27 21:23:05

标签: java unit-testing powermock easymock

寻找关于为什么期望返回null而不是请求的mock的一些指导。有问题的模拟是Future,并且遵循与正确返回的其他模拟相同的模式。

为了向有powermock和easymock经验的人提供所有信息,我已经包含了所有代码,包括测试中的代码和设置模拟和行为的测试代码。有问题的期望是

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

产生null而不是返回模拟的Future。

任何想法都会受到赞赏。

P.S。测试此功能需要大量的模拟设置,我希望不会阻碍评估问题。任何建议删除不必要的模拟基础设施将不胜感激。

这是测试中的代码

    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 );
}

2 个答案:

答案 0 :(得分:0)

我发现了问题,这是我肯定会遇到很多其他问题的其中一个......

返回null的模拟可以解释为我错误地使用EasyMock来创建模拟而不是PowerMock:

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

将该行更改为

CloseableHttpAsyncClient mockAsyncClient =
                                         PowerMock.createMock( CloseableHttpAsyncClient.class );
测试通过了。

原因是PowerMock拥有用于创建的模拟,并且只能验证这些模拟的行为。 PowerMock包装了EasyMock,因此需要对受控制的模拟进行可视化。

对于受此问题影响的人,请提出问题。不知道为什么我被拒绝了,但请让这个答案更容易被发现。

谢谢,罗宾。

答案 1 :(得分:0)

我在这里结束的原因是我想尝试whenNew(SomeClass.class).withAnyArguments()这样的课程:

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

证明withAnyArguments()与varargs不匹配。就我而言,解决方法是:

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