2017-03-07 11 views
2

generics 및 TypeTokens를 사용하여 JSON을 deserialize하는 서비스 코드가 있습니다. 이 서비스는 generic 매개 변수 유형을 유지하는 복잡한 TypeToken을 deserialize하는 데 필요합니다.복잡한 유형 토큰의 올바른 구성을 단위 테스트 할 수 있습니까?

<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()을 테스트하고 올바른 클래스를 얻지 만 generic 유형을 테스트하는 방법을 모르겠습니다.

@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 참조에 할당하려고하면이 작업을 수행해야합니다. 또 다른 시나리오는 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 문제 없습니다. –