如何模拟riak Java客户端? [英] How to mock riak java client?

查看:137
本文介绍了如何模拟riak Java客户端?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试对使用com.basho.riak:riak-client:2.0.0的代码进行单元测试.我嘲笑了所有riak客户类,并希望得到一个无用但有效的测试.但是,此操作失败,并带有空指针:

I'm trying to unit test code that uses com.basho.riak:riak-client:2.0.0. I mocked all riak client classes and was hoping to get a useless but working test. However, this fails with a null pointer:

java.lang.NullPointerException
  at com.basho.riak.client.api.commands.kv.KvResponseBase.convertValues(KvResponseBase.java:243)
  at com.basho.riak.client.api.commands.kv.KvResponseBase.getValue(KvResponseBase.java:150)
  at com.basho.riak.client.api.commands.kv.FetchValue$Response.getValue(FetchValue.java:171)

我的测试如下:

    @Test public void test() {         
        RiakClient riakClient = mock(RiakClient.class);

        @SuppressWarnings("unchecked")
        RiakCommand<FetchValue.Response, Location> riakCommand = (RiakCommand<FetchValue.Response, Location>) mock(RiakCommand.class);

        Response response = mock(Response.class);
        when(riakClient.execute(riakCommand)).thenReturn(response);
        Response returnedResponse = riakClient.execute(riakCommand);

        when(response.getValue(Object.class)).thenReturn(new Object());
        MyPojo myData = returnedResponse.getValue(MyPojo.class);
        // Make assertions
    }

如何对使用riak客户端的测试代码进行单元化?最终,我想确保使用了预期的类型/存储桶/键组合,并确保了预期的RiakCommand运行了.

How do you unit test code that uses the riak client? Eventually I would like to ensure that the expected type/bucket/key combination is used and that the expected RiakCommand is run.

我进一步研究了FetchValue类,并发现了以下结构:
FetchValue -是public final

I dug more into the FetchValue class and found this structure:
FetchValue - is public final

FetchValue.Response
-是public static
-具有程序包专用的构造函数Response(Init<?> builder)

FetchValue.Response
- is public static,
- has a package-private constructor Response(Init<?> builder)

FetchValue.Response.Init<T>是:
-protected static abstract class Init<T extends Init<T>> extends KvResponseBase.Init<T>

FetchValue.Response.Builder:
static class Builder extends Init<Builder>
-使用build()表示:return new Response(this);

And there is FetchValue.Response.Builder:
static class Builder extends Init<Builder>
- with build() that: return new Response(this);

我假设Mockito在内部类中的某个地方迷路了,而我的呼叫最终在KvResponseBase.convertValues中抛出了NP. KvResponseBase.convertValues假定值是List<RiakObject>,我看不到分配它的明智方法.

I assume that Mockito gets lost somewhere among the inner classes and my call ends up in KvResponseBase.convertValues, where the NP is thrown. KvResponseBase.convertValues assumes a List<RiakObject> of values and I see no sane way of assigning it.

推荐答案

我对您的情况进行了调查.我将您的示例简化为这个简单的SSCCE:

I have investigate a bit your case. I have reduce your example to this simple SSCCE:

import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
import org.junit.Test;
import com.basho.riak.client.api.commands.kv.FetchValue.Response;

public class RiakTest {
    @Test
    public void test() throws Exception {
        Response response = mock(Response.class);
        given(response.getValue(Object.class)).willReturn(new Object());
    }
}

会引发此错误:

java.lang.NullPointerException
at com.basho.riak.client.api.commands.kv.KvResponseBase.convertValues(KvResponseBase.java:243)
at com.basho.riak.client.api.commands.kv.KvResponseBase.getValue(KvResponseBase.java:150)
at com.basho.riak.client.api.commands.kv.FetchValue$Response.getValue(FetchValue.java:171)
at RiakTest.test(RiakTest.java:12)

经过一番挖掘,我认为我已经确定了问题所在.这是您试图存根从程序包(可见性)类继承的公共方法:

After some digging, i think i have identified the problem. It is that you are trying to stub a public method which is inherited from a package (visibility) class:

abstract class KvResponseBase {
    public <T> T getValue(Class<T> clazz) {
    }
}

似乎Mockito无法对该方法进行存根,因此调用了真正的方法,并抛出了NullPointerException(由于访问了空成员:values). 需要注意的重要一件事是,如果此函数调用未失败,则Mockito将显示适当的错误:

It seems that Mockito fails to stub this method so the real one is invoked and a NullPointerException is thrown (due to an access of a null member: values). One important thing to note is that if this function invocation not fails, Mockito would show a proper error:

org.mockito.exceptions.misusing.MissingMethodInvocationException: 
    when() requires an argument which has to be 'a method call on a mock'.
    For example:
        when(mock.getArticles()).thenReturn(articles);

    Also, this error might show up because:
    1. you stub either of: final/private/equals()/hashCode() methods.
       Those methods *cannot* be stubbed/verified.
       Mocking methods declared on non-public parent classes is not supported.
    2. inside when() you don't call method on mock but on some other object.


我想这是Mockito的错误或局限性,所以我在 Mockito跟踪器中打开了一个问题/a>我用简单的课程重述了你的情况.


I guess it is a Mockito bug or limitation so i have open an issue in the Mockito tracker where i have reproduce your case with simple classes.

更新

我打开的问题实际上是 Bytebuddy 模拟程序代替cglib模拟程序.在这里可以找到说明.

The issue i opened is in fact a duplicate of an existing one. This issue will not be fixed but a workaround exists. You may use the Bytebuddy mockmaker instead of the cglib one. Explanations could be found here.

这篇关于如何模拟riak Java客户端?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆