Java 如何对Mockito模拟的对象使用Gson TypeAdapter?
我想模拟通过TypeAdapter传入Gson的对象,如下所示:Java 如何对Mockito模拟的对象使用Gson TypeAdapter?,java,unit-testing,gson,mockito,Java,Unit Testing,Gson,Mockito,我想模拟通过TypeAdapter传入Gson的对象,如下所示: @RunWith(MockitoJUnitRunner.class) public class SceneExporterTest { @Test public void testWriter() { List<SceneObject> sceneObjects = mockSceneObjects(); Gson gson = new GsonBuilder().registerTypeAdapte
@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;
}
}
场景对象是相当重的对象,我不想在测试中正常地实例化它。那么有没有可能只是嘲笑它?我也不想使用Spies。以这种方式创建的
SceneObject
实例的运行时类型:mock(SceneObject.class)
是SceneObject$MockitoMock$
以以下方式创建的SceneObject
实例的运行时类型:new SceneObject()
为SceneObject
因此,当Gson的TypeAdapterRuntimeTypeWrapper
在其上下文中为模拟对象查找注册的TypeAdapter
时,它将找不到,因为您的SceneExporter
已针对SceneObject.class
注册
这实际上是说,模拟的SceneObject
不是类型的SceneObject
(它实际上是SceneObject
的一个子类),因此Gson将找不到您的定制类型适配器
如果您这样声明Gson
Gson gson = new GsonBuilder().registerTypeAdapter(mock(SceneObject.class).getClass(), new SceneExporter()).create();
。。。然后它将找到您的定制类型适配器,但注册看起来“关闭”,不是吗?这感觉像是一个只测试的专业
如果你真的必须模拟场景对象
,那么我认为你需要注册一个,但是如果你这么做只是为了支持这个测试用例,那感觉就像是一个只测试的限制流到了“主”源代码树中。因此,最简单的解决方案可能是:
- 创建
SceneObject的真实实例
- 使用Mockito
Spy
删除在SceneExporter
java.lang.UnsupportedOperationException: Attempted to serialize java.lang.Class: com.editor.api.scene.objects.SceneObject. Forgot to register a type adapter?
Gson gson = new GsonBuilder().registerTypeAdapter(mock(SceneObject.class).getClass(), new SceneExporter()).create();