java - 如何对复杂 TypeToken 的正确配置进行单元测试?

标签 java unit-testing generics gson guava

我有一些使用泛型和 TypeTokens 反序列化 JSON 的服务代码。需要该服务来反序列化保留其通用参数类型的复杂 TypeToken。

这是创建它的代码:

<T extends IPolicy> TypeToken<PolicyWrapper<T>> makePolicyWrapperTypeToken(Class<T> policyClass) {
    TypeToken<T> policyTypeToken = TypeToken.of(policyClass);
    return new TypeToken<PolicyWrapper<T>>() {}
        .where(new TypeParameter<T>() {}, policyTypeToken);
  }

似乎 TypeToken 无法正常工作,因为我从 GSON 收到类转换错误。

java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap 
cannot be cast to com.myStuff.IPolicy

看来我调试的时候是对的。 toString() 函数表明它知道它的泛型类型参数:

com.myStuff.PolicyWrapper<com.myStuff.PolicyImpl>

最后,我有一个单元测试。它通过但不测试泛型类型参数。我测试了 TypeToken 的 rawType() 并获得了正确的类,但我不确定如何测试它的通用类型。

@Test
 public void makePolicyWrapperTypeToken() throws NoSuchMethodException {

    TypeToken<?> wrapperToken = makePolicyWrapperTypeToken(PolicyImpl.class);
    assertEquals(wrapperToken.getRawType(), PolicyWrapper.class);

     //the getContent returns a list but it needs the generic type tested
     TypeToken<?> contentToken = wrapperToken.resolveType(PolicyWrapper.class.getMethod("getContent").getGenericReturnType());
     assertEquals(contentToken.getRawType(), List.class);

  }

最佳答案

It appears that the TypeToken isn't working correctly because I get a class cast error from GSON. java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to com.myStuff.IPolicy

不是真的。在您的情况下,看起来 Gson 在反序列化时没有收到足够的类型信息。 LinkedTreeMap是 Gson 内部 Gson 映射实现,默认情况下 Gson 用于反序列化具有任意结构的未知类型的对象。例如,如果通用类参数化信息由于某种原因丢失/删除,则可能会发生这种情况。例如,private final List<IPolicy> list;可以通过 ProGuard 等工具处理,因此它可能变成 private final List list;除非-keepattributes Signature被使用——一般来说它是合法的 Java 代码,但 Gson 没有足够的类型信息并使用 LinkedTreeMap .这就是您尝试将这样的列表元素分配给 IPolicy 时应该得到的结果引用。另一种情况是 typeToken.getRawType()而不是 type.getToken() : 原始类型不包含参数化信息,所以 new TypeToken<List<IPolicy>>(){}.getRawType()只是一个List.class -- 仍然没有关于使 Gson 使用默认策略的元素类型的信息。

the getContent returns a list but it needs the generic type tested

只需使用 TypeToken.getType()返回 java.lang.reflect.Type这是所有类型的基本接口(interface)。参数化泛型类型用 ParameterizedType 表示与更一般的 Type 不同,它提供了有关类型参数化的更多信息确实如此,并且此信息也可以使用类型标记构建。因此,以下断言为真:

// not really necessary, but just for the demonstration purposes:
assertTrue(contentToken.getType() instanceof ParameterizedType);
// this is enough:
assertEquals(new TypeToken<List<PolicyImpl>>() {}.getType(), contentToken.getType());

关于java - 如何对复杂 TypeToken 的正确配置进行单元测试?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42655399/

相关文章:

java - 暂停 Java Sequencer 重置节奏

c++ - 测试使用协作者和模板化方法的类

c# - 如何声明一个泛型类型的泛型约束

java - 布局管理器的推荐

java - JSF中是否有 "abstract"组件?

java - Android 应用程序滑动 viewpager 和滚动 recyclerview 非常慢,如何查明原因?

java - 为什么 PowerMockito 没有正确模拟此类?

java - 尝试使用 Mockito 模拟 Apache HTTP 客户端时出现的问题

java - 泛型语法 map.entry

Java - 通用抽象类的通用列表