Also fing ich an, 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 verspotten, ohne sie oder so zu simulieren. Ich möchte also Folgendes festlegen:
when(classIwantToTest.object.get().methodWhichReturnsAList(input))thenReturn(ListcreatedInsideTheTestClass)
Aber egal welche when-Klausel ich mache, ich bekomme immer eine NullpointerException, was natürlich Sinn macht, weil die Eingabe null ist.
Auch wenn ich versuche, eine andere Methode von einem Objekt zu verspotten:
when(object.method()).thenReturn(true)
Dort bekomme ich auch einen Nullpointer, da 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 wird.
Ist es ein grundsätzliches 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);
}
classIwantToTest.object.get()
Ergebnis kein Schein, oder dasget()
gibt null zurück. Aber bitte posten Sie Ihren Code, zeigen Sie Ihren Test und die Initialisierung Ihrer Mocks.Antworten:
Der Standardrückgabewert von Methoden, die Sie noch nicht gestoppt haben, ist
false
für boolesche Methoden, eine leere Sammlung oder Map für Methoden, die Sammlungen oder Maps zurückgeben, undnull
andere.Dies gilt auch für Methodenaufrufe innerhalb
when(...)
. In Sie sind Beispielwhen(myService.getListWithData(inputData).get())
wird eine Nullpointer verursachen , damyService.getListWithData(inputData)
istnull
- es vorher wurde nicht gerodet.Eine Möglichkeit besteht darin, Mocks für alle Zwischenrückgabewerte zu erstellen und diese vor der Verwendung zu stubben. Zum Beispiel:
Alternativ können Sie beim Erstellen eines Modells eine andere Standardantwort angeben, damit Methoden ein neues Modell anstelle von null zurückgeben:
RETURNS_DEEP_STUBS
Sie sollten das Javadoc von Mockito.RETURNS_DEEP_STUBS lesen, das dies ausführlicher erklärt und auch einige Warnungen bezüglich seiner Verwendung enthält.
Ich hoffe das hilft. Beachten Sie nur, dass Ihr Beispielcode anscheinend mehr Probleme aufweist, z. B. fehlende Anweisungen zum Bestätigen oder Überprüfen und Aufrufen von Setzern für Mocks (was keine Auswirkungen hat).
quelle
Ich hatte dieses Problem und mein Problem war, dass ich meine Methode mit
any()
anstelle von aufriefanyInt()
. So hatte ich:und ich musste es ändern zu:
Ich habe keine Ahnung, warum das eine NullPointerException erzeugt hat. Vielleicht hilft das der nächsten armen Seele.
quelle
any()
, dass für alle Variablen gearbeitet wird und sich als NPE manifestiert, ist gleichbedeutend mit einem Cyberkriegsangriff auf Entwicklerteams.Ich hatte das gleiche Problem und mein Problem war einfach, dass ich die Klasse mit @RunWith nicht richtig kommentiert hatte. Stellen Sie in Ihrem Beispiel sicher, dass Sie:
@RunWith(MockitoJUnitRunner.class) public class Test { ...
Sobald ich das getan habe, sind die NullPointerExceptions verschwunden.
quelle
Für zukünftige Leser besteht eine weitere Ursache für NPE bei der Verwendung von Mocks darin, zu vergessen, 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"); // ... }
Stellen Sie außerdem sicher, dass Sie JUnit für alle Anmerkungen verwenden. Ich habe einmal versehentlich einen Test mit @Test von testNG erstellt, sodass @Before nicht damit funktioniert hat (in testNG lautet die Anmerkung @BeforeTest).
quelle
org.junit.jupiter.api.Test
stattdessen verwenden möchte,import org.junit.Test
was dazu führte, dass die Mocks anscheinend null waren.Für mich war der Grund, warum ich NPE bekam, dass ich
Mockito.any()
beim Verspotten von Primitiven verwendet habe. Ich fand heraus, dass durch den Wechsel zur Verwendung der richtigen Variante von mockito die Fehler beseitigt werden.Um beispielsweise eine Funktion zu verspotten, die ein Grundelement
long
als Parameter verwendet, anstatt sie zu verwendenany()
, sollten Sie spezifischer sein und diese durchany(Long.class)
oder ersetzenMockito.anyLong()
.Hoffe das hilft jemandem.
quelle
org.mockito.exceptions.misusing.InvalidUseOfMatchersException: Misplaced or misused argument matcher detected... You cannot use argument matchers outside of verification or stubbing.
Stellen Sie sicher, dass Sie Ihre Mocks initialisieren.
JUnit4
verwenden@Before
@Before public void setup() { MockitoAnnotations.initMocks(this); }
JUnit5
verwenden@BeforeEach
@BeforeEach public void setup() { MockitoAnnotations.initMocks(this); }
Zur
JUnit5
Überprüfung verwenden Sie auch ordnungsgemäße Importe.import org.junit.runner.RunWith import org.mockito.junit.MockitoJUnitRunner; @RunWith(MockitoJUnitRunner.class)
quelle
Corner Fall:
Wenn Sie mit Scala und Sie versuchen , einen erstellen
any
Matcher auf einem Wert Klasse , werden Sie ein wenig hilfreich NPE bekommen.Also gegeben
case class ValueClass(value: Int) extends AnyVal
, was Sie tun möchten, istValueClass(anyInt)
stattany[ValueClass]
when(mock.someMethod(ValueClass(anyInt))).thenAnswer { ... val v = ValueClass(invocation.getArguments()(0).asInstanceOf[Int]) ... }
Bei dieser anderen SO-Frage geht es genauer darum, aber Sie würden sie verpassen, wenn Sie nicht wissen, dass das Problem bei Wertklassen liegt.
quelle
Sie müssen die MockitoAnnotations.initMocks (diese) Methode initialisieren, um mit Anmerkungen versehene Felder zu initialisieren.
@Before public void initMocks() { MockitoAnnotations.initMocks(this); }
Weitere Einzelheiten finden Sie unter Doc
quelle
org.junit.jupiter.api.BeforeEach
insted of@Before
hat mir geholfen.@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 to verwendenContext mockContext;
@Mock Context mockContext;
Es funktioniert jedoch nur, wenn Sie @RunWith (MockitoJUnitRunner.class) verwenden . Gemäß Mockito können Sie ein Scheinobjekt erstellen, indem Sie entweder @Mock oder Mockito.mock (Context.class) verwenden. ,
Ich habe eine NullpointerException erhalten, weil ich @RunWith (PowerMockRunner.class) verwendet habe. Stattdessen habe ich zu @RunWith (MockitoJUnitRunner.class) gewechselt. Es funktioniert einwandfrei
quelle
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 von :
@Mock private exampleService exampleServiceMock;
quelle
Die Antwort von Ed Webb hat in meinem Fall geholfen. Stattdessen können Sie auch versuchen, hinzuzufügen
@Rule public Mocks mocks = new Mocks(this);
wenn du
@RunWith(JUnit4.class)
.quelle
In meinem Fall habe ich das Hinzufügen zuerst verpasst
Dies kann also 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)
quelle
Keine dieser Antworten hat bei mir funktioniert. Diese Antwort löst das Problem von OP nicht, aber da dieser Beitrag der einzige ist, der beim Googeln dieses Problems auftaucht, teile ich meine Antwort hier.
Ich bin auf dieses Problem gestoßen, als ich Unit-Tests für Android geschrieben habe. Das Problem war , dass die Tätigkeit , dass ich verlängert teste
AppCompatActivity
stattActivity
. Um dies zu beheben, konnte ich nur ersetzenAppCompatActivity
mit ,Activity
da ich es nicht wirklich brauchen. Dies ist möglicherweise nicht für alle eine praktikable Lösung, aber hoffentlich hilft es jemandem, die Grundursache zu kennen.quelle
Keine der obigen Antworten hat mir geholfen. Ich hatte Mühe zu verstehen, warum Code in Java funktioniert, aber nicht in Kotlin.
Dann habe ich es aus diesem Thread herausgefunden .
Sie müssen Klassen- und Mitgliedsfunktionen erstellen
open
, andernfalls wurde NPE ausgelöst.Nach der
open
Durchführung begannen Funktionstests zu bestehen.Sie können auch das "All-Open" -Plugin des Compilers verwenden :
quelle
Bei Verwendung von JUnit 5 oder höher. Sie müssen die mit Anmerkungen versehene Klasse
@Mock
in ein@BeforeEach
Setup einfügen.quelle
Ein weiteres häufiges Problem ist, dass die Methodensignatur versehentlich als "endgültig" deklariert wird.
Dieser fängt eine Menge Leute auf, die an Codebasen arbeiten, die Checkstyle unterliegen und die Notwendigkeit verinnerlicht haben, Mitglieder als zu markieren
final
.dh im Beispiel des OP:
object.method()
Stellen Sie sicher, dass dies
method()
nicht deklariert ist alsfinal
:public final Object method() { }
Mockito kann sich nicht über eine endgültige Methode lustig machen und dies wird als verpackte NPE erscheinen:
Tief in der Fehlermeldung ist Folgendes vergraben:
Also, this error might show up because you use argument matchers with methods that cannot be mocked. Following methods *cannot* be stubbed/verified: final/private/equals()/hashCode(). Mocking methods declared on non-public parent classes is not supported.
quelle
Da dies dem Problem, das ich hatte, am nächsten kommt, ist es das erste Ergebnis, das auftaucht, und ich habe keine angemessene Antwort gefunden. Ich werde hier die Lösung für zukünftige arme Seelen veröffentlichen:
any()
funktioniert nicht, wenn die Methode der verspotteten Klasse einen primitiven Parameter verwendet.public Boolean getResult(String identifier, boolean switch)
Das Obige erzeugt genau das gleiche Problem wie OP.
Lösung, wickeln Sie es einfach ein:
public Boolean getResult(String identifier, Boolean switch)
Letzteres löst die NPE.
quelle
In meinem Fall lag es am falschen Import der @ Test-Annotation
Stellen Sie sicher, dass Sie den folgenden Import verwenden
import org.junit.jupiter.api.Test;
quelle