2016-11-29 4 views
0

Ich versuche, Unit-Test unter Verwendung von Powermockito für folgende Methode zu schreiben -Griff anonyme Klasse mit Generics in Mockito

public String getGenerator(String json) throws IOException { 
    String jwt = ""; 
    ObjectMapper mapper = new ObjectMapper(); 

    // convert JSON string to Map 
    Map<String, Object> map = mapper.readValue(json, new TypeReference<Map<String, Object>>() { 
    }); // Here passing TypeReference annonymously 

    // Create a JWT 
    JWTGenerator generator = new JWTGenerator(); 
    if (map != null && map.size() > 0) { 
     jwt = generator.createJWT(map); 
    } 

    return jwt; 
} 

I Testmethode geschrieben habe wie -

@Test 
public void testGetJWTGenerator() throws Exception { 
    ObjectMapper mockMapper = PowerMockito.mock(ObjectMapper.class); 
    PowerMockito.whenNew(ObjectMapper.class).withNoArguments().thenReturn(mockMapper); 

    JWTGenerator mockJWTDecoder = PowerMockito.mock(JWTGenerator.class); 
    PowerMockito.whenNew(JWTGenerator.class).withNoArguments().thenReturn(mockJWTDecoder); 

    Map<String, Object> anyMap = new HashMap<String, Object>(); 
    anyMap.put("testStr", new Object()); 

    TypeReference<Map<String, Object>> mockTypeReference = (TypeReference<Map<String, Object>>) PowerMockito.mock(TypeReference.class); 
    PowerMockito.whenNew(TypeReference.class).withNoArguments().thenReturn(mockTypeReference); 

    PowerMockito.when(mockMapper.readValue(Mockito.anyString(), Mockito.eq(mockTypeReference))).thenReturn(anyMap); 
    PowerMockito.when(mockJWTDecoder.createJWT(anyMap)).thenReturn(Mockito.anyString()); 
    utilityController = new UtilityController(); 
    utilityController.getJWTGenerator("{\"someStr\":\"someStr\"}"); 
    Mockito.verify(mockJWTDecoder, Mockito.times(1)).createJWT(anyMap); 
} 

Wenn ich diesen Test Mich betreiben immer bekommen, es zu sagen fehlgeschlagen -

Wanted but not invoked: 
jWTGenerator.createJWT(
    {[email protected]} 
); 

es ist wie Stub sieht nicht so funktioniert, wie ich immer für das „null“ erhalten Zeile -

Map<String, Object> map = mapper.readValue(json, new TypeReference<Map<String, Object>>() { 
     }); // Here passing TypeReference annonymously 

Ist es wegen der anonymen Instanziierung der TypeReference-Klasse?

Antwort

3

Ja, es ist wegen der anonymen inneren Klasse. Insbesondere Sie PowerMockito sagen, den Anruf zu new TypeReference ersetzen:

PowerMockito.whenNew(TypeReference.class).withNoArguments() 
    .thenReturn(mockTypeReference); 

Aber was Sie tatsächlich schaffen, ist eine anonyme Klasse, die TypeReference erstreckt, kein TypeReference selbst:

Map<String, Object> map = mapper.readValue(
    json, new TypeReference<Map<String, Object>>() {}); 

Das wird zu sei besonders schwierig für dich. Mein normaler Rat ist hier "don't mock data objects" wie TypeReference, weil es ein Token-/Wert-/Datenobjekt ohne Abhängigkeit ist, das schwer auf Reflexion arbeitet, aber es auch doesn't support equals die Art, wie seine Cousins ​​in Guice und Guava es tun; Du kannst nicht einfach deine eigene TypeReference in deinem Test erstellen und eq mit einem echten in deiner Klasse vergleichen.

Sie sollten noch nicht Mock TypeReference, aber Sie müssen auch einstellen, wie Sie dagegen behaupten:

  • die anonyme TypeReference Unterklasse zu einer benannten Äquivalent Extract, wenn Jackson Sie können, und verwenden Sie dann isA, um seinen Typ zu überprüfen.
  • Extrahieren Sie die TypeReference auf eine sichtbare Konstante, und überprüfen Sie die Referenzgleichheit darauf.
  • Verwenden Sie eine Captor und überprüfen Sie den generischen Typ der TypeReference mithilfe Reflexion später.
  • Wechseln Sie zu Mockito.<TypeReference<Map<String, Object>>>any(), die technisch auf der Matchers Klasse oder ArgumentMatchers in neueren Versionen von Mockito ist. Es ist unwahrscheinlich, dass sich der Wert ändert, daher können Ihr System und Ihr Test pragmatischer und robuster sein, wenn Sie den Check ignorieren, als wenn Sie PowerMock ansonsten überzeugen.
  • Im Idealfall verwenden Sie echte Abhängigkeiten, wo immer Sie können und überprüfen Sie einfach, dass die Funktion funktioniert, nicht, dass Sie mit den richtigen Mitarbeitern auf die Art und Weise interagieren, die Ihre Implementierung passiert. Eine Arbeitsfunktion ist das, wonach Sie suchen, richtig?
+0

Danke für detaillierte Erklärung. Ich wechselte zu Mockito. >> any() und es funktioniert. – Saurabh