Gibt es eine Möglichkeit, mit Mockito einige Methoden in einer Klasse zu verspotten, andere jedoch nicht?
Zum Beispiel Stock
möchte ich in dieser (zugegebenermaßen erfundenen) Klasse die Werte verspotten getPrice()
und getQuantity()
zurückgeben (wie im Test-Snippet unten gezeigt), aber ich möchte getValue()
, dass die Multiplikation wie in der Stock
Klasse codiert durchgeführt wird
public class Stock {
private final double price;
private final int quantity;
Stock(double price, int quantity) {
this.price = price;
this.quantity = quantity;
}
public double getPrice() {
return price;
}
public int getQuantity() {
return quantity;
}
public double getValue() {
return getPrice() * getQuantity();
}
@Test
public void getValueTest() {
Stock stock = mock(Stock.class);
when(stock.getPrice()).thenReturn(100.00);
when(stock.getQuantity()).thenReturn(200);
double value = stock.getValue();
// Unfortunately the following assert fails, because the mock Stock getValue() method does not perform the Stock.getValue() calculation code.
assertEquals("Stock value not correct", 100.00*200, value, .00001);
}
Antworten:
Um Ihre Frage direkt zu beantworten: Ja, Sie können einige Methoden verspotten, ohne andere zu verspotten. Dies wird als partieller Schein bezeichnet . Weitere Informationen finden Sie in der Mockito-Dokumentation zu Teilverspottungen .
Für Ihr Beispiel können Sie in Ihrem Test Folgendes tun:
In diesem Fall wird jede Methodenimplementierung verspottet, sofern
thenCallRealMethod()
in derwhen(..)
Klausel nichts anderes angegeben ist.Es gibt auch die Möglichkeit umgekehrt mit Spion statt Spott :
In diesem Fall sind alle Methodenimplementierungen real, es sei denn, Sie haben ein verspottetes Verhalten mit definiert
when(..)
.Es gibt eine wichtige Gefahr, wenn Sie
when(Object)
mit Spion wie im vorherigen Beispiel verwenden. Die reale Methode wird aufgerufen (da siestock.getPrice()
zuvorwhen(..)
zur Laufzeit ausgewertet wird). Dies kann ein Problem sein, wenn Ihre Methode Logik enthält, die nicht aufgerufen werden sollte. Sie können das vorherige Beispiel folgendermaßen schreiben:Eine andere Möglichkeit kann sein, zu verwenden
org.mockito.Mockito.CALLS_REAL_METHODS
, wie zum Beispiel:Dies delegiert nicht gestubbte Aufrufe an reale Implementierungen.
Doch mit Ihrem Beispiel, ich glaube , es wird immer noch fehlschlagen, da die Umsetzung
getValue()
beruht aufquantity
undprice
stattgetQuantity()
undgetPrice()
, das ist , was Sie verspottet haben.Eine andere Möglichkeit besteht darin, Verspottungen insgesamt zu vermeiden:
quelle
Stock stock = spy(Stock.class);
Dies scheint falsch zu sein, diespy
Methode scheint nur Objekte zu akzeptieren, keine Klassen.doReturn(retval).when(spyObj).methodName(args)
undwhen(spyObj.methodName(args)).thenReturn(retval)
Das teilweise Verspotten einer Klasse wird auch über Spy in mockito unterstützt
Überprüfen Sie die
1.10.19
und2.7.22
Dokumente für eine detaillierte Erklärung.quelle
Laut Dokumentation :
quelle
class NaughtyLinkedList extends LinkedList { public int size() { throw new RuntimeException("don't call me");} } @Test public void partialMockNaughtLinkedList(){ List mock = mock(NaughtyLinkedList.class, CALLS_REAL_METHODS); mock.add(new Object()); // this calls the real function when(mock.size()).thenReturn(2); // For whatever reason, this lines throws the RuntimeException. assertEquals(2,mock.size()); }
Das funktioniert nicht. Aus welchem Grund auch immer, wenn "wann" ausgeführt wird, führt es tatsächlich die Methode aus, die verspottet werden soll. Code:Was Sie wollen, ist
org.mockito.Mockito.CALLS_REAL_METHODS
gemäß den Dokumenten:So sollte Ihr Code aussehen:
Der Anruf zu
Stock stock = mock(Stock.class);
Anrufen,org.mockito.Mockito.mock(Class<T>)
der so aussieht:Die Dokumente des Werts
RETURNS_DEFAULTS
sagen:quelle
withSettings()...
? Es scheint, dassorg.mockito.internal.stubbing.answers.CallsRealMethods()
(zum Beispiel) die Arbeit machen könnte ... und der Javadoc für diese Klasse sagt ausdrücklich, dass es für Teilspott verwendet wird ...thenReturn
wird die Methode tatsächlich ausgeführt (was Probleme verursachen kann, obwohl dies in diesem Beispiel nicht derdoReturn
Fall ist ), und ist daher in einem solchen Fall vorzuziehen ...?Teilweise Verspottung mit Mockitos Spionagemethode könnte die Lösung für Ihr Problem sein, wie bereits in den obigen Antworten angegeben. Bis zu einem gewissen Grad stimme ich zu, dass es für Ihren konkreten Anwendungsfall möglicherweise angemessener ist, die DB-Suche zu verspotten. Aus meiner Erfahrung ist dies nicht immer möglich - zumindest nicht ohne andere Problemumgehungen -, die ich als sehr umständlich oder zumindest fragil betrachten würde. Beachten Sie, dass partielles Verspotten nicht mit Verbündetenversionen von Mockito funktioniert. Sie haben mindestens 1.8.0 verwendet.
Ich hätte nur einen einfachen Kommentar für die ursprüngliche Frage geschrieben, anstatt diese Antwort zu veröffentlichen, aber StackOverflow erlaubt dies nicht.
Nur noch eine Sache: Ich kann wirklich nicht verstehen, dass hier oft eine Frage gestellt wird, die einen Kommentar mit "Warum Sie das tun wollen" erhält, ohne zumindest zu versuchen, das Problem zu verstehen. Besonders wenn es darum geht, sich teilweise zu verspotten, gibt es wirklich viele Anwendungsfälle, die ich mir vorstellen kann, wo es nützlich wäre. Deshalb haben die Jungs von Mockito diese Funktionalität bereitgestellt. Diese Funktion sollte natürlich nicht überbeansprucht werden. Wenn wir jedoch über Testfall-Setups sprechen, die sonst nicht auf sehr komplizierte Weise erstellt werden könnten, sollte Spionage verwendet werden.
quelle