2017-03-07 6 views
2

genericsとTypeTokensを使用してJSONを逆シリアル化するサービスコードがあります。このサービスは、汎用パラメータ型を保持する複雑なTypeTokenを非直列化するために必要です。ここで複雑な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); 
    } 

私はGSONからクラスキャストエラーが出るので、TypeTokenが正しく動作していないことが表示されます。

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); 

    } 

答えて

1

私はGSONからクラスキャストエラーが発生しますので、TypeTokenが正しく動作していないことが表示されます。 java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to com.myStuff.IPolicy

実際はありません。あなたのケースでは、Gsonがデシリアライズ中に十分な型情報を受け取らないようです。 LinkedTreeMapは、Gsonがデフォルトで任意の構造を持つ未知の型のオブジェクトを逆シリアル化するために使用する内部Gsonマップ実装です。たとえば、ジェネリッククラスのパラメータ化情報が何らかの理由で失われたり消去されたりする場合があります。例えば、private final List<IPolicy> list;は、ProGuardのようなツールで処理することができるので、-keepattributes Signatureを使用しないとprivate final List list;になる可能性があります - 一般的に合法Javaコードですが、Gsonは型情報がなく、LinkedTreeMapを使用します。そして、あなたは一度そのようなリスト要素をIPolicy参照に割り当てようとしなければなりません。もう1つのシナリオはtype.getToken()の代わりにtypeToken.getRawType()です。生の型にはパラメータ化情報が含まれていないので、new TypeToken<List<IPolicy>>(){}.getRawType()はちょうどList.classです.Gsonにデフォルト戦略を使用させる要素の種類に関する情報はまだありません。

のgetContentは、リストを返しますが、それは一般的なタイプは、ちょうどすべてのタイプの基本インタフェースですjava.lang.reflect.Typeを返すことTypeToken.getType()を使用

をテストしなければなりません。パラメータ化されたジェネリック型は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()); 
+0

私が見るには、あなたの歓迎を – superbAfterSemperPhi

+0

@superbAfterSemperPhi問題ありませんに感謝します。 –

関連する問題