如何在mockito中模拟Gson

huangapple 未分类评论57阅读模式
标题翻译

How to mock Gson in mockito

问题

在我的应用程序中,有几个被调用的REST资源,我正在使用Gson作为解析接收到的响应的库。在为上述方法编写单元测试时,由于Gson是一个final类,我无法模拟Gson类。

在互联网上进行了一些研究后,我发现应该在src/test/resources/mockito-extensions下创建一个名为org.mockito.plugins.MockMaker的文件,其内容如下:

mock-maker-inline

但是我仍然无法使它正常工作。当运行上述测试用例时(由于gson对象未被正确模拟),我会收到以下异常:

com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 1

	at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:176)
	at com.google.gson.Gson.fromJson(Gson.java:803)
	at com.google.gson.Gson.fromJson(Gson.java:768)
	at com.google.gson.Gson.fromJson(Gson.java:717)
	at com.google.gson.Gson.fromJson(Gson.java:689)
	at org.kasun.sample.client.supportjira.impl.GroupRestClientImpl.addUser(GroupRestClientImpl.java:104)
	at org.kasun.sample.client.GroupRestClientImplTest.addUserToAGroup(GroupRestClientImplTest.java:102

请查看我的类,如下所示:

被测试的类:

import com.google.gson.Gson;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import org.testing.kasun.client.supportjira.dto.SaveResult;

import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

public class GroupRestClientImpl {
    private Gson gson = new Gson();

    // 其他代码...

}

测试类:

class TestBase {
    // 部分代码...

}

public class GroupRestClientImplTest extends TestBase {
    // 部分代码...
}

如果你需要关于这些代码的任何进一步解释或翻译,请随时提问。

英文翻译

In my application, there are few REST resources been invoked and I am using Gson as the library for parsing the responses received. While writing unit tests for the above methods I am unable to mock the Gson class as it is a final class.
While doing some research over the internet I found that a file named org.mockito.plugins.MockMaker should be created at src/test/resources/mockito-extensions with the content of the following,

mock-maker-inline

but still am unable to get it worked. What I am doing wrong.

I am getting the following exception when running the above test case (due to the gson object is not being properly mocked)

com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 1

	at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:176)
	at com.google.gson.Gson.fromJson(Gson.java:803)
	at com.google.gson.Gson.fromJson(Gson.java:768)
	at com.google.gson.Gson.fromJson(Gson.java:717)
	at com.google.gson.Gson.fromJson(Gson.java:689)
	at org.kasun.sample.client.supportjira.impl.GroupRestClientImpl.addUser(GroupRestClientImpl.java:104)
	at org.kasun.sample.client.GroupRestClientImplTest.addUserToAGroup(GroupRestClientImplTest.java:102

Please find my classes as follows,

Class been tested:

import com.google.gson.Gson;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import org.testing.kasun.client.supportjira.dto.SaveResult;

  
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
  
  
  public class GroupRestClientImpl{
    private Gson gson = new Gson();

    @Override
    public SaveResult addUser(User user, Group group) {

        WebResource resource = client.resource(baseUri + "/" + GROUP_URI_PREFIX + "/user?groupname=" + group.getName());
        ClientResponse response = resource.accept(MediaType.APPLICATION_JSON).type(MediaType.APPLICATION_JSON)
                .post(ClientResponse.class, user);

        String jsonText;
        if (response.getStatus() != Response.Status.CREATED.getStatusCode()) {
            jsonText = response.getEntity(String.class);
            JiraError jiraError = gson.fromJson(jsonText, JiraError.class);
            throw new JiraException(jiraError.toString());
        }
        jsonText = response.getEntity(String.class);
        SaveResult saveResults = gson.fromJson(jsonText, SaveResult.class);
        return saveResults;
    }

}

Test Classes:

class TestBase {

static final String JIRA_API_URL = "http://www.jira.com/jira/rest/api/2";
static final String MEDIA_TYPE_JSON = MediaType.APPLICATION_JSON;

@Mock
Client client;

@Mock
WebResource webResource;

@Mock
WebResource.Builder webResourceBuilder;

@Mock
ClientResponse clientResponse;

@Mock
Gson gson;

void setupMocks(Class<?> postPayloadType) {

    initMocks(this);
    when(client.resource(anyString())).thenReturn(webResource);
    when(webResource.accept(anyString())).thenReturn(webResourceBuilder);
    when(webResourceBuilder.type(anyString())).thenReturn(webResourceBuilder);
    when(webResourceBuilder.get(eq(ClientResponse.class))).thenReturn(clientResponse);
    when(webResourceBuilder.post(eq(ClientResponse.class), any(postPayloadType))).thenReturn(clientResponse);
    when(clientResponse.getEntity(eq(String.class))).thenReturn("responseText");
}

@AfterMethod
protected void clearMocks() {

    reset(client);
    reset(webResource);
    reset(webResourceBuilder);
    reset(clientResponse);
    reset(gson);
}

}

public class GroupRestClientImplTest extends TestBase {

    private static final String JIRA_GROUP_API_URL = JIRA_API_URL + "/group";
    private static final String JIRA_GROUP_MEMBER_API_URL = JIRA_GROUP_API_URL + "/member?groupname=";
    private static final String JIRA_GROUP_MEMBER_ADD_API_URL = JIRA_GROUP_API_URL + "/user?groupname=";

    private GroupRestClient groupRestClient;

    @BeforeMethod
    public void initialize() throws URISyntaxException {

        super.setupMocks(Group.class);
        groupRestClient = new GroupRestClientImpl(new URI(JIRA_API_URL), client);
    }
    
   @Test
    public void addUserToAGroup() throws URISyntaxException {

        when(clientResponse.getStatus()).thenReturn(Response.Status.CREATED.getStatusCode());
        when(webResourceBuilder.post(eq(ClientResponse.class), any(User.class))).thenReturn(clientResponse);
        SaveResult saveResult = new SaveResult();
        when(gson.fromJson(anyString(), isA(SaveResult.class.getClass()))).thenReturn(saveResult);
//        when(gson.fromJson(anyString(), eq(SaveResult.class))).thenReturn(saveResult);


        User user = new User();
        Group group = new Group();
        group.setName("group");
        SaveResult result = groupRestClient.addUser(user, group);

        // Test if the SaveResult is correct.
        Assert.assertEquals(result, saveResult);
    }

答案1

得分: -1

根据Mockito的文档,这个功能是围绕着Java 9构建的。

这个模拟创建器是围绕着Java代理运行时附加来设计的;这需要一个兼容的JVM,它是JDK的一部分(或Java 9 VM)。

如果您使用的是9之前的版本,您可以:

在运行于Java 9之前的非JDK虚拟机上时,您可以通过在启动JVM时使用-javaagent参数手动添加Byte Buddy Java代理jar包。

英文翻译

According to Mockito's documentation, this is feature is built around Java 9.

> This mock maker has been designed around Java Agent runtime attachment ; this require a compatible JVM, that is part of the JDK (or Java 9 VM).

If you have a version prior to 9, you can:

> When running on a non-JDK VM prior to Java 9, it is however possible to manually add the Byte Buddy Java agent jar using the -javaagent parameter upon starting the JVM.

huangapple
  • 本文由 发表于 2020年3月16日 15:27:46
  • 转载请务必保留本文链接:https://java.coder-hub.com/60701854.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定