绑定完请刷新页面
取消
刷新

分享好友

×
取消 复制
riak教程 java,如何模拟riak Java客户端?
2022-05-24 14:29:08

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)

My test looks like this:

@Test public void test() {

RiakClient riakClient = mock(RiakClient.class);

@SuppressWarnings("unchecked")

RiakCommand riakCommand = (RiakCommand) 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

}

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.

EDIT: I dug more into the FetchValue class and found this structure:

FetchValue

- is public final

FetchValue.Response

- is public static,

- has a package-private constructor Response(Init> builder)

FetchValue.Response.Init is:

- protected static abstract class Init> extends KvResponseBase.Init

And there is FetchValue.Response.Builder:

static class Builder extends Init

- with build() that: return new Response(this);

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 of values and I see no sane way of assigning it.

解决方案

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

}

}

which throws this error:

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 getValue(Class clazz) {

}

}

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.

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.

UPDATE

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 KV
创建时间:2022-04-19 09:50:17
Riak KV
展开
订阅须知

• 所有用户可根据关注领域订阅专区或所有专区

• 付费订阅:虚拟交易,一经交易不退款;若特殊情况,可3日内客服咨询

• 专区发布评论属默认订阅所评论专区(除付费小栈外)

技术专家

查看更多
  • 飘絮絮絮丶
    专家
戳我,来吐槽~