【问题标题】:How to mock Gson in mockito如何在 mockito 中模拟 Gson
【发布时间】:2020-03-16 07:27:46
【问题描述】:

在我的应用程序中,调用的 REST 资源很少,我使用 Gson 作为库来解析收到的响应。在为上述方法编写单元测试时,我无法模拟 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();

    @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;
    }

}

测试类:

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

【问题讨论】:

  • gson 是否在 GroupRestClientImpl 中自动连线?
  • 也许 GroupRestClientImpl 的构造函数设置 gson 可以帮助...
  • @Smile 很抱歉在课堂上错过了那句话,更新了GroupRestClientImp。请看
  • 如果您通过junit执行进行调试,您是否看到GroupRestClientImpl中的gson是用模拟对象或真实对象初始化的?
  • 没有使用模拟 Gson,因为您在代码中调用了 new Gson()。解决方法是使when(clientResponse.getEntity(eq(String.class))).thenReturn("responseText"); 这个模拟返回一个字符串,该字符串与序列化为JiraError.classSaveResult.class 的json 匹配,具体取决于所需的测试。

标签: java unit-testing testing mockito gson


【解决方案1】:

根据 Mockito 的 documentation,这是围绕 Java 9 构建的功能。

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

如果您有 9 之前的版本,您可以:

在 Java 9 之前的非 JDK VM 上运行时,可以在启动 JVM 时使用 -javaagent 参数手动添加 Byte Buddy Java 代理 jar。

【讨论】:

    猜你喜欢
    • 2015-02-20
    • 1970-01-01
    • 1970-01-01
    • 2018-10-08
    • 2019-08-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多