繁体   English   中英

如何将Gson TypeAdapter与Mockito嘲笑的对象一起使用?

[英]How to use Gson TypeAdapter with an object mocked by Mockito?

我想通过TypeAdapter模拟一个传入Gson的对象,如下所示:

@RunWith(MockitoJUnitRunner.class)
public class SceneExporterTest {

@Test
public void testWriter() {
    List<SceneObject> sceneObjects = mockSceneObjects();
    Gson gson = new GsonBuilder().registerTypeAdapter(SceneObject.class, new SceneExporter()).create();

    String s = gson.toJson(sceneObjects); //This method ends up with an exception.
}

private List<SceneObject> mockSceneObjects() {
    List<SceneObject> sceneObjects = new LinkedList<>();
    for (int i = 0; i < 50; i++) {
        sceneObjects.add(mockSceneObject(i));
    }
    return sceneObjects;
}

private SceneObject mockSceneObject(int i) {
    SceneObject sceneObject = mock(SceneObject.class);
    //...
    return sceneObject;
}

}

我的类型适配器:

public class SceneExporter extends TypeAdapter<SceneObject> {

    @Override
    public void write(JsonWriter out, SceneObject value) throws IOException {
        out.name("position");
        out.value(toValue(value.getPosition()));
        out.name("scale");
        out.value(toValue(value.getScale()));
        out.name("rotation");
        out.value(toValue(value.getRotation()));
    }

    @Override
    public SceneObject read(JsonReader in) throws IOException {
        return null;
    }
}

但我最终得到了这样的例外:

java.lang.UnsupportedOperationException: Attempted to serialize java.lang.Class: com.editor.api.scene.objects.SceneObject. Forgot to register a type adapter?

场景对象是非常重的对象,我不想在测试中正常对象。 那么有可能只是嘲笑它吗? 我也不想使用间谍。

以这种方式创建的SceneObject实例的运行时类型: mock(SceneObject.class)SceneObject$MockitoMock$<SOMEID>

以这种方式创建的SceneObject实例的运行时类型: new SceneObject()SceneObject

因此,当Gson的TypeAdapterRuntimeTypeWrapper在其上下文中为TypeAdapter对象查找已注册的SceneObject.class ,它将找不到一个,因为您的SceneExporter已针对SceneObject.class进行了注册。

这实际上是说, SceneObject不是SceneObject 类型 (它实际上是SceneObject的子类),因此Gson将找不到您的定制类型适配器。

如果你像这样申报Gson ......

Gson gson = new GsonBuilder().registerTypeAdapter(mock(SceneObject.class).getClass(), new SceneExporter()).create();

...然后它找到你的定制型适配器,但注册看起来“关闭”不是吗? 这感觉就像是一个仅限测试的专业化。

如果你真的必须模拟SceneObject那么我认为你需要注册一个继承感知类型的适配器,但如果你这样做只是为了支持这个测试用例,那么感觉就像是一个仅限测试的限制流入“主”源代码树。 所以,也许最简单的解决方案是:

  • 创建SceneObject真实实例
  • 使用的Mockito Spy存根出具体的SceneObject ,其在调用干将SceneExporter

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM