在 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 找不到类型,但是我应该如何以及如何更改以使测试运行?
感谢罗马的澄清和帮助。在@RomanKonoval 的建议下,在方法中添加了一个参数,用于传递所需的类型信息:
我很乐意接受建设性的批评和评论。