【问题标题】:ClassCastException in MockitoMockito 中的 ClassCastException
【发布时间】:2016-01-30 07:31:01
【问题描述】:

我有以下方法,我正在尝试使用 Mockito 编写单元测试。我对 Mockito 还很陌生,并试图赶上。

测试方法

public synchronized String executeReadRequest(String url) throws Exception{

    String result = null;
    RestClient client = null;
    Resource res = null;
    logger.debug("Start executing GET request on "+url);

    try{
         client = getClient();
         res = client.resource(url);
         result = res.contentType(this.requestType).accept(this.responseType).get(String.class);
    }
    catch(Exception ioe){
        throw new Exception(ioe.getMessage());
    }
    finally{
        res = null;
        client = null;
    }

    logger.info("GET request execution is over with result : "+result);
    return result;
}

使用 Mockito 进行单元测试

@Test
public void testRestHandler() throws Exception {
    RestHandler handler = spy(new RestHandler());
    RestClient mockClient = Mockito.mock(RestClient.class,Mockito.RETURNS_DEEP_STUBS); 
    Resource mockResource = Mockito.mock(Resource.class,Mockito.RETURNS_DEEP_STUBS);

    doReturn(mockClient).when(handler).getClient();
    Mockito.when(mockClient.resource(Mockito.anyString())).thenReturn(mockResource);

  //ClassCastException at the below line
    Mockito.when(mockResource.contentType(Mockito.anyString()).accept(Mockito.anyString()).get(Mockito.eq(String.class))).thenReturn("dummy read result");

    handler.setRequestType(MediaType.APPLICATION_FORM_URLENCODED);
    handler.setResponseType(MediaType.APPLICATION_JSON);
    handler.executeReadRequest("abc");
}

但我在该行收到 ClassCastException

Mockito.when(mockResource.contentType(Mockito.anyString()).accept(Mockito.anyString()).get(Mockito.eq(String.class))).thenReturn("dummy read result");

例外

java.lang.ClassCastException: org.mockito.internal.creation.jmock.ClassImposterizer$ClassWithSuperclassToWorkAroundCglibBug$$EnhancerByMockitoWithCGLIB$$4b441c4d cannot be cast to java.lang.String

感谢任何帮助解决此问题。

非常感谢。

【问题讨论】:

    标签: java mockito


    【解决方案1】:

    存根期间的这种链接方式是不正确的:

    Mockito.when(
        mockResource.contentType(Mockito.anyString())
            .accept(Mockito.anyString())
            .get(Mockito.eq(String.class)))
        .thenReturn("dummy read result");
    

    即使您已将模拟设置为返回深存根,Matchers work via side-effects,所以这条线并没有达到您认为的效果。所有三个匹配器(anyString、anyString、eq)都会在调用when 期间进行评估,而你的代码可能会在最轻微的挑衅下抛出InvalidUseOfMatchersException——包括添加不相关的代码或稍后验证。

    这意味着您的问题不是eq(String.class) 的使用:这是 Mockito 试图在不属于它的地方使用 Class 匹配器。

    相反,您需要专门存根:

    Mockito.when(mockResource.contentType(Mockito.anyString()))
        .thenReturn(mockResource);
    Mockito.when(mockResource.accept(Mockito.anyString()))
        .thenReturn(mockResource);
    Mockito.when(mockResource.get(Mockito.eq(String.class))) // or any(Class.class)
        .thenReturn("dummy read response");
    

    请注意,这里的一些困难在于 Apache Wink 使用了 Builder 模式,这在 Mockito 中可能很费力。 (我在这里返回了 mockResource,但您可以想象返回特定的其他 Resource 对象,代价是稍后要求它们完全按照该顺序。)更好的方法可能是 use a default Answer that returns this whenever possible。

    【讨论】:

      【解决方案2】:

      通过将 get 调用更改为解决它

      get(Mockito.any(Class.class))
      

      【讨论】:

      • 虽然这段代码可以回答这个问题,但最好包含一些上下文,解释它是如何工作的以及何时使用它。从长远来看,纯代码的答案没有用处。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多