Javers 无法比较一些模拟对象

Javers cannot compare some mocked objects

我正试图找到一种方法来修复工作中的一些单元测试。我们使用 javers.compare() 来记录我们修改对象后的差异,但是出现了一个奇怪的错误,我几乎没有找到关于它的 none 信息。 我们所有的对象都实现了 Serializable 接口,当传递给 javers 时它会正确处理它们,在单元测试中当我传递一个模拟对象时,javers 正常运行,除非对象中有另一个对象。我已经让内部对象实现了 Serializable 接口,我试图让它们成为瞬态的,但没有任何效果。它总是失败。

正如我所说,如果对象被实例化,它们将被正常处理,但相同对象的模拟版本会导致错误。

javers.compare() 相比,mockito 模拟时来自此 class 的对象不会导致错误。

public class SomeEntry implements Serializable {
    private Long id;
    private String aString;
    private Double aNumber;
    private List<Long> aListOfNumbers;
}

来自此 class 的对象仅在被 mockito 模拟时才导致 javers.compare() 错误,如果正常实例化则不会。

public class OtherEntry implements Serializable {
    private Long id;
    private String aString;
    private Double aNumber;
    private SomeOtherEntry someOtherEntry;
}
public class SomeOtherEntry implements Serializable {
    private Long id;
}

OtherEntry 内部创建 SomeOtherEntry transient 什么都不做,并且会出现错误。

这是 i javers.compare() 使用模拟对象产生的错误

java.lang.UnsupportedOperationException: Attempted to serialize java.lang.Class: {classpath}/{classname} Forgot to register a type adapter?

    at com.google.gson.internal.bind.TypeAdapters.write(TypeAdapters.java:73)
    at com.google.gson.internal.bind.TypeAdapters.write(TypeAdapters.java:69)
    at com.google.gson.TypeAdapter.write(TypeAdapter.java:191)
    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:69)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.write(ReflectiveTypeAdapterFactory.java:127)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:245)
    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:69)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.write(ReflectiveTypeAdapterFactory.java:127)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:245)
    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:69)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.write(ReflectiveTypeAdapterFactory.java:127)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:245)
    at com.google.gson.Gson.toJson(Gson.java:704)
    at com.google.gson.Gson.toJsonTree(Gson.java:597)
    at com.google.gson.Gson.toJsonTree(Gson.java:576)
    at com.google.gson.internal.bind.TreeTypeAdapter$GsonContextImpl.serialize(TreeTypeAdapter.java:155)
    at org.javers.core.json.typeadapter.commit.CdoSnapshotStateTypeAdapter.lambda$toJson[=13=](CdoSnapshotStateTypeAdapter.java:28)
    at org.javers.core.metamodel.object.CdoSnapshotState.lambda$forEachProperty(CdoSnapshotState.java:61)
    at java.util.HashMap$EntrySet.forEach(HashMap.java:1044)
    at org.javers.core.metamodel.object.CdoSnapshotState.forEachProperty(CdoSnapshotState.java:61)
    at org.javers.core.json.typeadapter.commit.CdoSnapshotStateTypeAdapter.toJson(CdoSnapshotStateTypeAdapter.java:28)
    at org.javers.core.json.typeadapter.commit.CdoSnapshotStateTypeAdapter.toJson(CdoSnapshotStateTypeAdapter.java:13)
    at org.javers.core.json.JsonConverterBuilder.lambda$registerJsonTypeAdapterForType(JsonConverterBuilder.java:167)
    at com.google.gson.internal.bind.TreeTypeAdapter.write(TreeTypeAdapter.java:81)
    at com.google.gson.internal.bind.TreeTypeAdapter.write(TreeTypeAdapter.java:74)
    at com.google.gson.Gson.toJson(Gson.java:704)
    at com.google.gson.Gson.toJson(Gson.java:683)
    at com.google.gson.Gson.toJson(Gson.java:638)
    at com.google.gson.Gson.toJson(Gson.java:618)
    at org.javers.core.json.JsonConverter.toJson(JsonConverter.java:54)
    at org.javers.core.snapshot.ObjectHasher.hash(ObjectHasher.java:28)
    at org.javers.core.metamodel.object.GlobalIdFactory.createId(GlobalIdFactory.java:69)
    at org.javers.core.graph.LiveCdoFactory.create(LiveCdoFactory.java:29)
    at org.javers.core.graph.LiveCdoFactory.create(LiveCdoFactory.java:15)
    at org.javers.core.graph.EdgeBuilder$MultiEdgeContainerBuilderFunction.apply(EdgeBuilder.java:72)
    at org.javers.core.metamodel.type.CollectionType.mapToList(CollectionType.java:47)
    at org.javers.core.metamodel.type.CollectionType.map(CollectionType.java:34)
    at org.javers.core.graph.EdgeBuilder.createMultiEdge(EdgeBuilder.java:55)
    at org.javers.core.graph.ObjectGraphBuilder.buildMultiEdges(ObjectGraphBuilder.java:91)
    at org.javers.core.graph.ObjectGraphBuilder.buildEdges(ObjectGraphBuilder.java:71)
    at org.javers.core.graph.ObjectGraphBuilder.buildGraphFromCdo(ObjectGraphBuilder.java:58)
    at org.javers.core.graph.ObjectGraphBuilder.buildGraph(ObjectGraphBuilder.java:47)
    at org.javers.core.graph.LiveGraphFactory.createLiveGraph(LiveGraphFactory.java:39)
    at org.javers.core.diff.DiffFactory.buildGraph(DiffFactory.java:99)
    at org.javers.core.diff.DiffFactory.compare(DiffFactory.java:54)
    at org.javers.core.JaversCore.compare(JaversCore.java:173)
    at The class that is being tested.
    at The Unit Test.
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.runners.model.FrameworkMethod.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.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    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.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access[=13=]0(ParentRunner.java:58)
    at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
    at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
    at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:230)
    at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:58)

Javers 设计为使用静态 类,因此您编写的 类。您应该避免将 Hibernate 或 Mockito 动态生成的动态代理传递给 Javers。那些 类 添加了一些您肯定不会被压缩和版本控制的技术领域。参见 https://javers.org/documentation/domain-configuration/#ignoring-things

我的建议是,避免嘲笑你自己的 类,尤其是实体。这将使您的测试更强大,更简单。