wake-up-neo.com

Mockito - NullpointerException beim Stubbing der Methode

Also begann ich Tests für unser Java-Spring-Projekt zu schreiben. 

Was ich benutze, ist JUnit und Mockito. Es heißt, wenn ich die Option when () ... thenReturn () verwende, kann ich Dienste simulieren, ohne sie zu simulieren. Was ich also machen möchte, ist:

when(classIwantToTest.object.get().methodWhichReturnsAList(input))thenReturn(ListcreatedInsideTheTestClass)  

Unabhängig von der Wann-Klausel bekomme ich immer eine NullpointerException, was natürlich Sinn macht, weil die Eingabe null ist. 

Auch wenn ich versuche, eine andere Methode mit einem Objekt zu verspotten: 

when(object.method()).thenReturn(true)

Dort bekomme ich auch einen Nullpointer, weil die Methode eine Variable benötigt, die nicht gesetzt ist. 

Aber ich möchte when () .. thenReturn () verwenden, um diese Variable zu erstellen und so weiter. Ich möchte nur sicherstellen, dass, wenn eine Klasse diese Methode aufruft, egal was passiert, einfach true oder die obige Liste zurückgegeben werden.

Ist es im Grunde ein Missverständnis von meiner Seite oder stimmt etwas anderes nicht?

Code:

public class classIWantToTest implements classIWantToTestFacade{
        @Autowired
        private SomeService myService;

        @Override
        public Optional<OutputData> getInformations(final InputData inputData) {
            final Optional<OutputData> data = myService.getListWithData(inputData);
            if (data.isPresent()) {
                final List<ItemData> allData = data.get().getItemDatas();
                    //do something with the data and allData
                return data;
            }

            return Optional.absent();
        }   
}

Und hier ist meine Testklasse:

public class Test {

    private InputData inputdata;

    private ClassUnderTest classUnderTest;

    final List<ItemData> allData = new ArrayList<ItemData>();

    @Mock
    private DeliveryItemData item1;

    @Mock
    private DeliveryItemData item2;



    @Mock
    private SomeService myService;


    @Before
    public void setUp() throws Exception {
        classUnderTest = new ClassUnderTest();
        myService = mock(myService.class); 
        classUnderTest.setService(myService);
        item1 = mock(DeliveryItemData.class);
        item2 = mock(DeliveryItemData.class);

    }


    @Test
    public void test_sort() {
        createData();
        when(myService.getListWithData(inputdata).get().getItemDatas());

        when(item1.hasSomething()).thenReturn(true);
        when(item2.hasSomething()).thenReturn(false);

    }

    public void createData() {
        item1.setSomeValue("val");
        item2.setSomeOtherValue("test");

        item2.setSomeValue("val");
        item2.setSomeOtherValue("value");

        allData.add(item1);
        allData.add(item2);


}
27
user5417542

Der Standardwert für Rückgabewerte für Methoden, die Sie noch nicht erstellt haben, ist false für boolesche Methoden, eine leere Auflistung oder Map für Methoden, die Collections oder Maps zurückgeben, und andernfalls null.

Dies gilt auch für Methodenaufrufe innerhalb von when(...). In Ihrem Beispiel verursacht when(myService.getListWithData(inputData).get()) eine NullPointerException, da myService.getListWithData(inputData)null ist - es wurde zuvor nicht stubben.

Eine Option ist das Erstellen von Mocks für alle Zwischenrückgabewerte und das Stubben vor der Verwendung. Zum Beispiel:

ListWithData listWithData = mock(ListWithData.class);
when(listWithData.get()).thenReturn(item1);
when(myService.getListWithData()).thenReturn(listWithData);

Alternativ können Sie beim Erstellen eines Mock auch eine andere Standardantwort angeben, damit die Methoden einen neuen Mock anstelle von null zurückgeben: RETURNS_DEEP_STUBS

SomeService myService = mock(SomeService.class, Mockito.RETURNS_DEEP_STUBS);
when(myService.getListWithData().get()).thenReturn(item1);

Sie sollten den Javadoc von Mockito.RETURNS_DEEP_STUBS lesen, der dies ausführlicher erklärt und auch einige Warnungen über seine Verwendung enthält.

Ich hoffe das hilft. Beachten Sie, dass Ihr Beispielcode anscheinend weitere Probleme aufweist, z. B. fehlende Assert- oder Verify-Anweisungen und das Aufrufen von Setters für Mocks (was keine Auswirkungen hat).

34
ahu

Ich hatte dieses Problem und mein Problem war, dass ich meine Methode mit any() anstelle von anyInt() aufrief. So hatte ich:

doAnswer(...).with(myMockObject).thisFuncTakesAnInt(any())

und ich musste es ändern in:

doAnswer(...).with(myMockObject).thisFuncTakesAnInt(anyInt())

Ich habe keine Ahnung, warum dies eine NullPointerException hervorgerufen hat. Vielleicht hilft das der nächsten armen Seele.

68

Ich hatte das gleiche Problem und mein Problem war einfach, dass ich die Klasse nicht richtig mit @RunWith kommentiert hatte. Stellen Sie in Ihrem Beispiel sicher, dass Sie Folgendes haben:

@RunWith(MockitoJUnitRunner.class)
public class Test {
...

Nachdem ich das getan hatte, verschwanden die NullPointerExceptions.

31
Ed Webb

Für mich war der Grund, warum ich NPE bekam, dass ich Mockito.any() beim Spott von Primitiven verwendete. Ich fand, dass durch das Umschalten auf die richtige Variante von mockito die Fehler beseitigt werden.

Um beispielsweise eine Funktion zu simulieren, die ein primitives long als Parameter verwendet, anstatt any() zu verwenden, sollten Sie genauer sein und dieses durch any(Long.class) oder Mockito.anyLong() ersetzen.

Hoffe das hilft jemandem.

4
smac89

Eckfall:
Wenn Sie Scala verwenden und versuchen, einen any-Matcher für eine value-Klasse zu erstellen, erhalten Sie eine nicht hilfreiche NPE.

Wenn Sie also case class ValueClass(value: Int) extends AnyVal gegeben haben, möchten Sie ValueClass(anyInt) anstelle von any[ValueClass]

when(mock.someMethod(ValueClass(anyInt))).thenAnswer {
   ...
   val v  = ValueClass(invocation.getArguments()(0).asInstanceOf[Int])
   ...
}

Diese andere SO - Frage befasst sich genauer damit, aber Sie würden es vermissen, wenn Sie nicht wissen, dass das Problem mit Werteklassen zusammenhängt.

3
Vituel

Für zukünftige Leser besteht eine weitere Ursache für NPE beim Verwenden von Mocks darin, die Mocks wie folgt zu initialisieren:

@Mock
SomeMock someMock;

@InjectMocks
SomeService someService;

@Before
public void setup(){
    MockitoAnnotations.initMocks(this); //without this you will get NPE
}

@Test
public void someTest(){
    Mockito.when(someMock.someMethod()).thenReturn("some result");
   // ...
}
2
Tal Joffe
@RunWith(MockitoJUnitRunner.class) //(OR) PowerMockRunner.class

@PrepareForTest({UpdateUtil.class,Log.class,SharedPreferences.class,SharedPreferences.Editor.class})
public class InstallationTest extends TestCase{

@Mock
Context mockContext;
@Mock
SharedPreferences mSharedPreferences;
@Mock
SharedPreferences.Editor mSharedPreferenceEdtor;

@Before
public void setUp() throws Exception
{
//        mockContext = Mockito.mock(Context.class);
//        mSharedPreferences = Mockito.mock(SharedPreferences.class);
//        mSharedPreferenceEdtor = Mockito.mock(SharedPreferences.Editor.class);
    when(mockContext.getSharedPreferences(Mockito.anyString(),Mockito.anyInt())).thenReturn(mSharedPreferences);
    when(mSharedPreferences.edit()).thenReturn(mSharedPreferenceEdtor);
    when(mSharedPreferenceEdtor.remove(Mockito.anyString())).thenReturn(mSharedPreferenceEdtor);
    when(mSharedPreferenceEdtor.putString(Mockito.anyString(),Mockito.anyString())).thenReturn(mSharedPreferenceEdtor);
}

@Test
public void deletePreferencesTest() throws Exception {

 }
}

Alle oben genannten kommentierten Codes sind nicht erforderlich {mockContext = Mockito.mock(Context.class);}, , Wenn Sie @Mock Annotation für Context mockContext; verwenden. 

@Mock 
Context mockContext; 

Es funktioniert jedoch nur, wenn Sie @RunWith (MockitoJUnitRunner.class) verwenden. Gemäß Mockito können Sie ein Mock-Objekt erstellen, indem Sie entweder @Mock oder Mockito.mock (Context.class) verwenden.,

Ich habe NullpointerException erhalten, weil @RunWith (PowerMockRunner.class) verwendet wurde. Stattdessen habe ich zu @RunWith (MockitoJUnitRunner.class) gewechselt

1
anand krish

stand vor dem gleichen Problem, der Lösung, die für mich funktionierte:

Anstatt die Service-Schnittstelle zu verspotten, habe ich @InjectMocks verwendet, um die Service-Implementierung zu verspotten:

@InjectMocks
private exampleServiceImpl exampleServiceMock;

anstatt :

@Mock
private exampleService exampleServiceMock;
0

In meinem Fall habe ich das Hinzufügen zuerst verpasst 

PowerMockito.spy(ClassWhichNeedToBeStaticMocked.class);

daher kann dies für jemanden hilfreich sein, der einen solchen Fehler sieht

Java.lang.NullPointerException
    at org.powermock.api.mockito.internal.expectation.PowerMockitoStubberImpl.addAnswersForStubbing(PowerMockitoStubberImpl.Java:67)
    at org.powermock.api.mockito.internal.expectation.PowerMockitoStubberImpl.when(PowerMockitoStubberImpl.Java:42)
    at org.powermock.api.mockito.internal.expectation.PowerMockitoStubberImpl.when(PowerMockitoStubberImpl.Java:112)
0

sie müssen die Methode MockitoAnnotations.initMocks (this) initialisieren, um mit Anmerkungen versehene Felder zu initialisieren.

   @Before public void initMocks() {
       MockitoAnnotations.initMocks(this);
   }

weitere Informationen finden Sie unter Doc

0
Jacob

Keine der obigen Antworten hat mir geholfen. Ich hatte Mühe zu verstehen, warum Code in Java, aber nicht in Kotlin funktioniert.

Dann habe ich es aus diesem Thread herausgefunden .

Sie müssen Klassen- und Member-Funktionen open erstellen, andernfalls wurde NPE ausgelöst.

Nachdem die Funktion open ausgeführt wurde, wurden die Tests bestanden.

Sie können auch das "All-Open" -Plugin des Compilers verwenden :

Kotlin hat Klassen und ihre Mitglieder standardmäßig final, was die Verwendung von Frameworks und Bibliotheken wie Spring AOP erschwert Für diese Klassen muss offen sein . Das all-open Compiler Plugin passt Kotlin an die Anforderungen dieser Frameworks an und macht Klassen mit einer bestimmten Annotation annotiert und deren Mitglieder öffnen ohne das explizite open-Schlüsselwort.

0
azizbekian

Keine dieser Antworten funktionierte für mich. Diese Antwort löst das Problem von OP nicht. Da dieser Beitrag jedoch der einzige ist, der beim Googeln dieses Problems auftaucht, teile ich hier meine Antwort.

Ich bin auf dieses Problem gestoßen, als ich Unit-Tests für Android schrieb. Das Problem war, dass die von mir getestete Aktivität AppCompatActivity statt Activity erweitert wurde. Um dies zu beheben, konnte ich AppCompatActivity einfach durch Activity ersetzen, da ich es nicht wirklich brauchte. Dies ist möglicherweise nicht für jeden eine praktikable Lösung, aber hoffentlich hilft das Wissen um die Ursache für jemanden. 

0
mindreader

Ed Webbs Antwort hat in meinem Fall geholfen. Stattdessen können Sie auch hinzufügen 

  @Rule public Mocks mocks = new Mocks(this);

wenn Sie @RunWith(JUnit4.class).

0
lcn