我想模拟通过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
时,由于您的SceneExporter
已针对SceneObject.class
注册,因此将找不到一个。
这实际上是在说,模拟的SceneObject
不是 SceneObject
类型的(实际上是SceneObject
的子类),因此Gson找不到您定制的适配器。
如果您这样声明Gson
...Gson gson = new GsonBuilder().registerTypeAdapter(mock(SceneObject.class).getClass(), new SceneExporter()).create();
...然后会找到您的定制类型适配器,但是注册看起来“关闭”了吗?感觉就像是只测试的专业。
如果您真的必须模拟SceneObject
,那么我认为您需要注册一个inheritance aware type adapter,但是如果您只是为了支持此测试用例而这样做,那感觉就像是仅测试的限制正在渗入“主”源树。因此,也许最简单的解决方案是:SceneObject
的真实实例Spy
存根出在SceneObject
中调用的特定SceneExporter
吸气剂