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

Java 如何对复杂的TypeToken进行正确配置的单元测试?,java,unit-testing,generics,gson,guava,Java,Unit Testing,Generics,Gson,Guava,我有一些服务代码,它使用泛型和TypeToken来反序列化JSON。需要该服务来反序列化保持其泛型参数类型的复杂TypeToken 以下是创建它的代码: <T extends IPolicy> TypeToken<PolicyWrapper<T>> makePolicyWrapperTypeToken(Class<T> policyClass) { TypeToken<T> policyTypeToken = TypeToken

我有一些服务代码,它使用泛型和TypeToken来反序列化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);
  }
看起来我在调试时做对了。toString()函数表明它知道其泛型类型参数:

com.myStuff.PolicyWrapper<com.myStuff.PolicyImpl>
com.myStuff.PolicyWrapper
最后,我有一个单元测试。它通过测试,但不测试泛型类型参数。我测试了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);

  }
@测试
public void makePolicyWrapperTypeToken()引发NoSuchMethodException{
TypeToken wrapperToken=makePolicyWrapperTypeToken(PolicyImpl.class);
assertEquals(wrapperToken.getRawType(),PolicyWrapper.class);
//getContent返回一个列表,但需要测试泛型类型
TypeToken contentToken=wrapperToken.resolveType(PolicyWrapper.class.getMethod(“getContent”).getGenericReturnType());
assertEquals(contentToken.getRawType(),List.class);
}
TypeToken似乎无法正常工作,因为我从GSON获得了一个类强制转换错误。
java.lang.ClassCastException:com.google.gson.internal.LinkedTreeMap不能强制转换为com.myStuff.IPolicy

不是真的。在您的例子中,Gson在反序列化时似乎没有收到足够的类型信息
LinkedTreeMap
是一个内部Gson映射实现,默认情况下Gson用于反序列化具有任意结构的未知类型的对象。例如,如果泛型类参数化信息由于某种原因丢失/擦除,则可能会发生这种情况。例如,
私有最终列表可由ProGuard等工具处理,因此它可能成为
私有最终列表
除非使用了
-keepattributes签名
——一般来说,这是合法的Java代码,但Gson没有足够的类型信息,使用
LinkedTreeMap
。这是您在尝试将这样一个列表元素分配给
IPolicy
引用时应该得到的。另一个场景是
typeToken.getRawType()
而不是
type.getToken()
:原始类型不包含参数化信息,因此
new-typeToken(){}.getRawType()
只是一个
列表。class
——仍然没有关于使Gson使用默认策略的元素类型的信息

getContent返回一个列表,但需要测试泛型类型

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

//其实不需要,只是为了演示:
assertTrue(参数化类型的contentToken.getType()实例);
//这就足够了:
assertEquals(新的TypeToken(){}.getType(),contentToken.getType());
@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);

  }