Czy jest jakiś sposób, za pomocą Mockito, wyśmiewać niektóre metody w klasie, ale nie inne?
Na przykład w tej (wprawdzie wymyślonej) Stock
klasie chcę wyśmiewać wartości getPrice()
i getQuantity()
zwracać wartości (jak pokazano w fragmencie testowym poniżej), ale chcę, getValue()
aby wykonać mnożenie zgodnie z zakodowaniem w Stock
klasie
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);
}
Odpowiedzi:
Aby bezpośrednio odpowiedzieć na twoje pytanie, tak, możesz wyśmiewać niektóre metody bez wyśmiewania innych. Nazywa się to częściową próbą . Aby uzyskać więcej informacji, zobacz dokumentację Mockito na temat częściowych prób .
Na przykład w teście możesz wykonać następujące czynności:
W takim przypadku każda implementacja metody jest wyśmiewana, chyba że określono
thenCallRealMethod()
wwhen(..)
klauzuli.Istnieje również możliwość odwrotnej sytuacji ze szpiegiem zamiast kpiną :
W takim przypadku cała implementacja metody jest prawdziwa, z wyjątkiem sytuacji, w której zdefiniowano kpiące zachowanie
when(..)
.Jest jedna ważna pułapka, gdy używasz
when(Object)
szpiega, jak w poprzednim przykładzie. Wywołana zostanie prawdziwa metoda (ponieważstock.getPrice()
jest sprawdzana przedwhen(..)
uruchomieniem). Może to stanowić problem, jeśli metoda zawiera logikę, której nie należy wywoływać. Możesz napisać poprzedni przykład w ten sposób:Inną możliwością może być użycie
org.mockito.Mockito.CALLS_REAL_METHODS
, na przykład:To deleguje nieodebrane połączenia do rzeczywistych implementacji.
Jednak ze swoim przykładzie, wierzę, że jeszcze nie, ponieważ realizacja
getValue()
opiera się naquantity
iprice
, zamiastgetQuantity()
igetPrice()
, co jest, co pan wyśmiewany.Inną możliwością jest całkowite unikanie kpin:
źródło
Stock stock = spy(Stock.class);
Wydaje się to błędne,spy
metoda akceptuje tylko obiekty, a nie klasy.doReturn(retval).when(spyObj).methodName(args)
iwhen(spyObj.methodName(args)).thenReturn(retval)
Częściowe drwiny z klasy są również obsługiwane przez Szpiega w mockito
Sprawdź
1.10.19
i2.7.22
dokumenty, aby uzyskać szczegółowe wyjaśnienia.źródło
Według dokumentów :
źródło
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()); }
To nie działa Bez względu na przyczynę, kiedy „kiedy” jest wykonywane, faktycznie wykonuje metodę, która powinna być wyśmiewana. Kod:Co chcesz, to
org.mockito.Mockito.CALLS_REAL_METHODS
zgodnie z dokumentami:Zatem twój kod powinien wyglądać następująco:
Połączenie z
Stock stock = mock(Stock.class);
połączeniami,org.mockito.Mockito.mock(Class<T>)
które wygląda następująco:Dokumenty wartości
RETURNS_DEFAULTS
mówią:źródło
withSettings()...
? Wygląda na to, żeorg.mockito.internal.stubbing.answers.CallsRealMethods()
(na przykład) może wykonać zadanie ... a javadoc dla tej klasy wyraźnie mówi, że jest on przeznaczony do częściowego udawania ...thenReturn
Faktycznie wykona metodę (która może powodować problemy, chociaż nie w tym przykładzie), a więcdoReturn
jest lepiej w takim przypadku ...?Częściowe drwiny przy użyciu metody szpiegowskiej Mockito mogą być rozwiązaniem twojego problemu, jak już wspomniano w odpowiedziach powyżej. W pewnym stopniu zgadzam się, że w twoim konkretnym przypadku użycia bardziej odpowiednie może być wyśmiewanie wyszukiwania DB. Z mojego doświadczenia nie zawsze jest to możliwe - przynajmniej nie bez innych obejść - które uważałbym za bardzo kłopotliwe lub co najmniej kruche. Pamiętaj, że częściowe kpiny nie działają z sojuszniczymi wersjami Mockito. Używasz co najmniej 1.8.0.
Po prostu napisałbym prosty komentarz do oryginalnego pytania zamiast zamieszczać tę odpowiedź, ale StackOverflow nie pozwala na to.
Jeszcze jedna rzecz: Naprawdę nie rozumiem, że wiele razy tutaj zadawane jest pytanie z komentarzem „Dlaczego chcesz to zrobić” bez przynajmniej próby zrozumienia problemu. Tym bardziej, jeśli chodzi o potrzebę częściowego kpienia, istnieje naprawdę wiele przypadków użycia, które mogłem sobie wyobrazić, gdzie byłoby to przydatne. Właśnie dlatego chłopaki z Mockito zapewnili tę funkcjonalność. Nie należy oczywiście nadużywać tej funkcji. Ale kiedy mówimy o konfiguracjach przypadków testowych, których inaczej nie można byłoby ustalić w bardzo skomplikowany sposób, należy zastosować szpiegostwo.
źródło