RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1334052
Accepted
XelaNimed
XelaNimed
Asked:2022-10-01 17:37:23 +0000 UTC2022-10-01 17:37:23 +0000 UTC 2022-10-01 17:37:23 +0000 UTC

如何测试泛型方法?

  • 772

在 Eclipse 2021-09 上使用 JUnit 4.12 测试getPatches(Object, Object)的公共类中有一个静态方法:JsonUtil

import javax.annotation.Nonnull;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;

public static List<PatchOperation> getPatches(
    @Nonnull Object oldData,
    @Nonnull Object newData)
    throws IOException
{
    List<PatchOperation> _patchOperations = new ArrayList<>();
    ObjectMapper objectMapper = new ObjectMapper();

    String _oldDataJson = objectMapper.writeValueAsString(oldData);
    String _newDataJson = objectMapper.writeValueAsString(newData);

    JsonNode _oldJsonNode = objectMapper.readTree(_oldDataJson);
    JsonNode _newJsonNode = objectMapper.readTree(_newDataJson);

    JsonNode _patchData = com.github.fge.jsonpatch.diff.JsonDiff.asJson(_oldJsonNode, _newJsonNode);
    if (_patchData != null)
    {
        _patchOperations = objectMapper.convertValue(_patchData, new TypeReference<List<PatchOperation>>(){});
    }

    return _patchOperations;
}

这里,PatchOperation只是一个 POJO 类,用于反序列化JSON-Patch(参见RFC6902),用于对服务器的PATCH 请求:

import java.io.Serializable;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
public class PatchOperation implements Serializable
{
    private static final long serialVersionUID = 9999999999999999999L;
    
    @JsonProperty("op")
    public String Operation;
    
    @JsonProperty("path")
    public String Path;
    
    @JsonProperty("value")
    public Object Value;
    
    @JsonProperty("from")
    public String From;
    
    @Override
    public String toString() 
    {
        try
        {
            return new ObjectMapper().writeValueAsString(this);
        }
        catch ( JsonProcessingException e )
        {
            return super.toString();
        }
    }
}

方法的 JUnit 测试getPatches:

@Test public final void getPatchesTest()
            throws JsonProcessingException, IOException
{
    PatchTestItem _itemOne = new PatchTestItem();
    _itemOne.id = "ABC123";
    _itemOne.active = true;
    _itemOne.value = "First value";

    PatchTestItem _itemTwo = new PatchTestItem();
    _itemTwo.id = "ABC123";
    _itemTwo.active = true;
    _itemTwo.value = "Updated value";

    java.util.List<PatchOperation> _patches = JsonUtil.getPatches(_itemOne, _itemTwo);

    Assert.assertNotNull(_patches);
    Assert.assertEquals(1, _patches.size());
    // в следующей строке выбрасывает ошибку при тестировании обобщённого метода
    Assert.assertEquals("replace", _patches.get(0).Operation);
    Assert.assertEquals("/value", _patches.get(0).Path);
    Assert.assertEquals(_itemTwo.value, _patches.get(0).Value.toString());
    
    _itemTwo.value = _itemOne.value;
    _patches = JsonUtil.getPatches(_itemOne, _itemTwo);
    
    Assert.assertNotNull(_patches);
    Assert.assertEquals(0, _patches.size());
    
    _itemTwo.active = false;
    _itemTwo.value = "Updated value again";
    _patches = JsonUtil.getPatches(_itemOne, _itemTwo);
    
    Assert.assertNotNull(_patches);
}

测试正在运行,以这种形式一切都很好。
现在决定使用通用方法如下:

public static <T> List<T> getPatches(
    @Nonnull Object oldData,
    @Nonnull Object newData)
    throws IOException
{
    List<T> _patchOperations = new ArrayList<>();
    ObjectMapper objectMapper = new ObjectMapper();

    String _oldDataJson = objectMapper.writeValueAsString(oldData);
    String _newDataJson = objectMapper.writeValueAsString(newData);

    JsonNode _oldJsonNode = objectMapper.readTree(_oldDataJson);
    JsonNode _newJsonNode = objectMapper.readTree(_newDataJson);

    JsonNode _patchData = com.github.fge.jsonpatch.diff.JsonDiff.asJson(_oldJsonNode, _newJsonNode);
    if (_patchData != null)
    {
        _patchOperations = objectMapper.convertValue(_patchData, new TypeReference<List<T>>(){});
    }

    return _patchOperations;
}

上面的选项没有通过测试 - 它给出错误“找不到源”并掉入日志:

java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to xxx.xxx.xxx.xxx.xxx.PatchOperation
    at xxx.xxx.xxx.xxx.xxx.JsonUtilTest.getPatchesTest(JsonUtilTest.java:36)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:93)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:40)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:529)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:756)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:452)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:210)

当然,我知道问题是 JUnit 找不到类型,但是我应该如何以及如何更改以使测试运行?

java
  • 1 1 个回答
  • 10 Views

1 个回答

  • Voted
  1. Best Answer
    XelaNimed
    2022-10-04T14:38:37Z2022-10-04T14:38:37Z

    感谢罗马的澄清和帮助。在@RomanKonoval 的建议下,在方法中添加了一个参数,用于传递所需的类型信息:

    public static <T> T getPatches(
        @Nonnull Object oldData,
        @Nonnull Object newData,
        final TypeReference<T> typeRef)
        throws IOException
    {
        String _oldDataJson = objectMapper.writeValueAsString(oldData);
        String _newDataJson = objectMapper.writeValueAsString(newData);
    
        JsonNode _oldJsonNode = objectMapper.readTree(_oldDataJson);
        JsonNode _newJsonNode = objectMapper.readTree(_newDataJson);
    
        JsonNode _patchData = com.github.fge.jsonpatch.diff.JsonDiff.asJson(_oldJsonNode, _newJsonNode);
        return new ObjectMapper().convertValue(_patchData, typeRef);
    }
    // Пример использования:
    // final TypeReference<List<PatchOperation>> _typeRef =
    //       new TypeReference<List<PatchOperation>>() {};
    // List<PatchOperation> _patches =
    //       JsonUtil.getConvertedPatch(_itemOne, _itemTwo, _typeRef);
    

    我很乐意接受建设性的批评和评论。

    • 0

相关问题

  • wpcap 找不到指定的模块

  • 如何以编程方式从桌面应用程序打开 HTML 页面?

  • Android Studio 中的 R.java 文件在哪里?

  • HashMap 初始化

  • 如何使用 lambda 表达式通过增加与原点的距离来对点进行排序?

  • 最大化窗口时如何调整元素大小?

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    表格填充不起作用

    • 2 个回答
  • Marko Smith

    提示 50/50,有两个,其中一个是正确的

    • 1 个回答
  • Marko Smith

    在 PyQt5 中停止进程

    • 1 个回答
  • Marko Smith

    我的脚本不工作

    • 1 个回答
  • Marko Smith

    在文本文件中写入和读取列表

    • 2 个回答
  • Marko Smith

    如何像屏幕截图中那样并排排列这些块?

    • 1 个回答
  • Marko Smith

    确定文本文件中每一行的字符数

    • 2 个回答
  • Marko Smith

    将接口对象传递给 JAVA 构造函数

    • 1 个回答
  • Marko Smith

    正确更新数据库中的数据

    • 1 个回答
  • Marko Smith

    Python解析不是css

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5