2016-07-04 8 views
0

Ich habe Probleme, eine verspottete Methode eines Objekts aufzurufen, das von einer anderen verspotteten Methode meines verspotteten Dienstes zurückgegeben wird.NPE beim Aufruf eines verspotteten Objekts (Mockito)

Insbesondere möchte ich das Ergebnis von "builder.get()" verspotten. Aber wenn "builder.get()" aufgerufen wird, erhalte ich eine Nullzeiger-Ausnahme (Builder ist null).

My-Controller wie folgt aussieht:

@RestController 
public class MyController { 

@Autowired 
MyClientService myClientService; 

@RequestMapping("/myMethod") 
@Validated 
public MyCustomResponse myMethod(@RequestParam String someId, @Valid @ModelAttribute("someParams") SomeHeaderParams someHeaderParams) { 
    final String targetString = myClientService.buildTargetString("resource", someId + "/myMethod"); 
    final Map<String, String> headerMap = myClientService.getHeaderParams(someHeaderParams); 

    Map<String, String> paramsMap = new HashMap<>(); 
    paramsMap.put("SOME_ID", someId); 

    Invocation.Builder builder = myClientService.buildRequest(targetString, headerMap, paramsMap); 
    final Response response = builder.get(); 
    return response.readEntity(MyCustomResponse.class); 
} 

}

Und mein Test wie folgt aussieht:

@RunWith(MockitoJUnitRunner.class) 
public class MyControllerTests { 

@Spy 
@InjectMocks 
MyController myControllerController; 

@Mock 
MyClientService myClientService; 

SomeHeaderParams someHeaderParams; 

@Before 
public void init() { 
    someHeaderParams = new SomeHeaderParams(); 
    someHeaderParams.setCommunicationLanguage("de"); 
    someHeaderParams.setCrId("123"); 
    someHeaderParams.setMemberUserId("qwe"); 
} 

@Test 

public void myTest() { 
    MyCustomResponse myResponseMock = mock(MyCustomResponse.class); 
    Response responseMock = mock(Response.class); 
    Mockito.when(responseMock.readEntity(MyCustomResponse.class)).thenReturn(myResponseMock); 

    Invocation.Builder builderMock = mock(Invocation.Builder.class); 
    Mockito.when(builderMock.get()).thenReturn(responseMock); 
    Mockito.when(myClientService.buildRequest(Mockito.anyString(), Mockito.anyMap(), Mockito.anyMap())).thenReturn(builderMock); 
    MyCustomResponse response = myControllerController.myMethod("myBusinessId", someHeaderParams); 
} 

} Dies sollte nicht allzu schwierig sein, aber ich fand keine Beispiele wo die verspottete Methode einen anderen Mock zurückgab, fand ich nur Beispiele, wo es einen String zurückgibt.

+1

Eine Frage: In Ihrem Test, ist die Linie 'Mockito.when (auskunftClientService. buildRequest (Mockito.anyString(), Mockito.anyMap(), Mockito.anyMap())) thenReturn (builderMock). ' sein soll ' Mockito.when (someService.buildRequest (Mockito.anyString(), M ockito.anyMap(), Mockito.anyMap())). thenReturn (builderMock); ' ? –

+0

yep, änderte es, danke – IwantToKnow

+1

** 1 ** Wo bekommen Sie die NPE? ** 2 ** Ich sehe nirgendwo im Code 'MockitoAnnotations.initMocks (this);' um deine Mocks zu initialisieren; Benutzt du einen anderen Läufer wie [MockitoJUnitRunner] (http://site.mockito.org/mockito/docs/current/org/mockito/runners/MockitoJUnitRunner.html)? ** 3 ** Sie können [einen Schein konfigurieren, um eine ganze Hierarchie von Mocks/Stubs zurückzugeben] (http://site.mockito.org/mockito/docs/current/org/mockito/Answers.html) anstelle von Standardwerten (Null, falsch, 0, usw.). Dies ermöglicht eine Scheinkonfiguration (selbst zwischenzeitliche), wodurch die Notwendigkeit vermieden wird, zwischenzeitliche Mocks selbst zu erstellen. – Morfic

Antwort

1

Die zweite Reihe von myMethod(String someId, SomeHeaderParams someHeaderParams) in MyController Klasse:

Es ist ein Aufruf der Methode myClientService.getHeaderParams(SomeHeaderParams): I don‘ Wenn Sie die Mock-Konfiguration für diesen Aufruf sehen, sollte sie null zurückgeben, und wenn die Methode buildRequest(String, Map, Map) aufgerufen wird, sollte sie ein null als zweites Argument erhalten. Der Matcher anyMap() ist nicht erfüllt, und deshalb gibt er den Standardwert null statt des konfigurierten Schein für die Klasse Invocation.Builder zurück.

Die Lösung kann sein, die folgenden in Ihrem Test enthalten:

Mockito.when(myClientService.getHeaderParams(Mockito.any(SomeHeaderParams.class))).thenReturn(new HashMap<String, String>()); 

So:

@Test 
public void myTest() { 
    MyCustomResponse myResponseMock = mock(MyCustomResponse.class); 
    Response responseMock = mock(Response.class); 
    Mockito.when(responseMock.readEntity(MyCustomResponse.class)).thenReturn(myResponseMock); 

    Invocation.Builder builderMock = mock(Invocation.Builder.class); 
    Mockito.when(builderMock.get()).thenReturn(responseMock); 
    Mockito.when(myClientService.getHeaderParams(Mockito.any(SomeHeaderParams.class))).thenReturn(new HashMap<String, String>()); 
    Mockito.when(myClientService.buildRequest(Mockito.anyString(), Mockito.anyMap(), Mockito.anyMap())).thenReturn(builderMock); 
    MyCustomResponse response = myControllerController.myMethod("myBusinessId", someHeaderParams); 
} 
+1

Ich muss auch hinzufügen "Mockito.when (myClientService.buildTargetString (Mockito.anyString(), Mockito.anyString())). ThenReturn (" asd ");" aber deine Antwort ist richtig, danke! :) – IwantToKnow

0

Mit Mockito können Sie Ihre Mocks so konfigurieren, dass sie alles zurückgeben, was Sie wollen, so dass Sie tatsächlich eine Mock-Methode konfigurieren können, um einen weiteren Mock zurückzugeben.

Mit Blick auf den Code der Frage sehe ich einen wichtigen Unterschied.

In der Klasse MyController, die dritte Reihe der Methode a() ist:

final Invocation.Builder builder = someService.buildRequest(targetString, someMap); 

In der Testklasse, siebte Reihe der Testverfahren wird die mock wie folgt konfiguriert:

Mockito.when(someService.buildRequest(Mockito.anyString(), Mockito.anyMap(), Mockito.anyMap())).thenReturn(builderMock); 

So ist die in MyController Klasse verwendete Methode buildRequest(String, Map), aber die verspottete Methode ist buildRequest(String, Map, Map), das ist nicht die gleiche Methode, die tatsächlich von MyController verwendet wird.

Es sollte gut funktionieren, wenn Sie diese Zeile in Ihrem Test mit ersetzen:

Mockito.when(someService.buildRequest(Mockito.anyString(), Mockito.anyMap())).thenReturn(builderMock); 
+0

Leider nicht, ich hatte tatsächlich das "Mockito.when (someService.buildRequest (Mockito.anyString(), Mockito.anyMap())). DannReturn (builderMock);" in meinem Code wurde es gerade durch meine Verschleierung verloren;) Ich habe nun meinen Code in der Frage etwas bearbeitet. – IwantToKnow