Mockito - 无法初始化 HttpEntity 上的间谍



我正在测试的代码工作正常,日志是正确的。


测试错误: 连接器测试:无法初始化@Spy带批注的字段"实体"。


  • 为什么我不能在 http 实体上使用验证?
  • 有没有更好的方法来测试它?否则我应该监视日志吗?

要测试的类:

public class Connector {
    private static final String hostname = "localhost";
    private int varnishPort = 8000;
    private int connectionTimeout = 5000; //millis
    private int requestTimeout = 5000;
    private int socketTimeout = 5000;
    private final HttpHost host;
    private HttpClient httpClient;
    private HttpEntity entity;
    private HttpResponse response;
    public Connector(){
        host = new HttpHost(this.hostname, this.varnishPort);
        RequestConfig.Builder requestBuilder = RequestConfig.custom();
        requestBuilder = requestBuilder.setConnectTimeout(connectionTimeout);
        requestBuilder = requestBuilder.setConnectionRequestTimeout(requestTimeout);
        requestBuilder = requestBuilder.setSocketTimeout(socketTimeout);
        HttpClientBuilder builder = HttpClientBuilder.create();     
        builder.setDefaultRequestConfig(requestBuilder.build());
        httpClient = builder.build();
    }

    public void invalidateVarnishCache( String level, String idDb ) {
        try{
            String xPurgeRegex = level+"/"+idDb+"$";
            Header header = new BasicHeader( "X-Purge-Regex", xPurgeRegex );
            BasicHttpRequest purgeRequest = new BasicHttpRequest("PURGE", "/" );
            purgeRequest.setHeader(header);
            response = httpClient.execute(host, purgeRequest);
            entity = response.getEntity();
            int statusCode = response.getStatusLine().getStatusCode();
            if( statusCode >= 300 ){
                int respLength = entity.getContent().available();
                byte[] errorResp = new byte[ respLength ];
                entity.getContent().read(errorResp, 0, respLength);
                // log error
            }else{
                // log success
            }
            EntityUtils.consume(entity);
        }catch(Exception e){
            // log exception
        }
    }
}

我的测试:

@RunWith(MockitoJUnitRunner.class)
public class ConnectorTest {
    @Mock
    private HttpClient httpClient;
    // @Spy
    // private HttpEntity entity;
    @InjectMocks
    private Connector varnishPurger = new Connector();

    @Test
    public void purgeFail() throws Exception{
        HttpResponse response500 = new BasicHttpResponse( new ProtocolVersion( "HTTP/1.1", 0, 0), 500, "NO!_TEST" );
        HttpEntity entity500 = new StringEntity("BAD entity. [test]");
        response500.setEntity(entity500);
        doReturn( response500 )
        .when( httpClient ).execute( isA(HttpHost.class), isA(BasicHttpRequest.class) );
        varnishPurger.invalidateVarnishCache("level_test_500", "id_test_500");
        // verify( entity, times( 1 ) ).getContent().available();  // HOW DO I MAKE THIS WORK?
    }
    ...
}
HttpEntity是一个

接口,它不能被监视,只能被嘲笑。所以只需用@Mock更改注释,或者另一种选择是声明一个初始化的实例:

@Spy HttpEntity entity = new BasicHttpEntity();

无论如何,异常消息很清楚为什么会发生这种情况:

org.mockito.exceptions.base.MockitoException: Unable to initialize @Spy annotated field 'entity'.
Type 'HttpEntity' is an interface and it cannot be spied on.
    at org.mockito.internal.runners.JUnit45AndHigherRunnerImpl$1.withBefores(JUnit45AndHigherRunnerImpl.java:27)
    at org.junit.runners.BlockJUnit4ClassRunner.methodBlock(BlockJUnit4ClassRunner.java:276)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.mockito.internal.runners.JUnit45AndHigherRunnerImpl.run(JUnit45AndHigherRunnerImpl.java:37)
    at org.mockito.runners.MockitoJUnitRunner.run(MockitoJUnitRunner.java:62)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:234)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:74)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
Caused by: org.mockito.exceptions.base.MockitoException: Type 'HttpEntity' is an interface and it cannot be spied on.
    ... 21 more

此行为与 Mockito.spy(Object) 一致,如果没有实例,则无法调用此方法。然而,最近的Mockito.spy(Class)并没有抱怨这一点。这可能是未移植到注释子系统的功能。

尽管如此,监视接口在语义上是错误的,因为它没有行为。

我是这样解决的:

class MockHttpEntity implements HttpEntity{
    String msg = "Test_";
    InputStream inps;
    int count = 0;
    public MockHttpEntity(String msg){
        this.msg += msg;
        inps = IOUtils.toInputStream(this.msg);
    }
    @Override
    public InputStream getContent(){
        System.out.println("n"+(++count)+") Mocked getContent() called.n");
        return inps;
    }
    public int times(){
        return count;
    }
    @Override public void       consumeContent(){  }
    @Override public Header     getContentEncoding(){ return null; }
    @Override public long       getContentLength(){ return 0; }
    @Override public Header     getContentType(){ return null;}
    @Override public boolean    isChunked(){ return false; }
    @Override public boolean    isRepeatable(){ return false; }
    @Override public boolean    isStreaming(){ return false; }
    @Override public void       writeTo(OutputStream outstream){  }
}

@RunWith(MockitoJUnitRunner.class)
public class ConnectorTest {    
    @Mock
    private HttpClient httpClient;
    @InjectMocks
    private Connector varnishPurger = new Connector();

    @Test
    public void purgeFailureResponse() throws Exception{
        MockHttpEntity mockedHttpEntity = new MockHttpEntity("bad entity");
        HttpResponse response500 = new BasicHttpResponse( new ProtocolVersion( "HTTP/1.1", 0, 0), 500, "NO!_TEST" );
        response500.setEntity( mockedHttpEntity );
        doReturn( response500 )
        .when( httpClient ).execute( isA(HttpHost.class), isA(BasicHttpRequest.class) );
        varnishPurger.invalidateVarnishCache("level_test_no", "id_test_no");
        Assert.assertTrue( mockedHttpEntity.times() == 2 );
    }
    ...
}

相关内容

  • 没有找到相关文章

最新更新