2013-07-30 12 views
9

Próbuję przetestować klasę abstrakcyjną, a Mockito nie inicjuje moich zmiennych składowych. Oto prosty przykład, aby pokazać ci mój problem.Dlaczego Mockito pomija inicjalizację zmiennej składowej mojej abstrakcyjnej klasy

Jest to klasa abstrakcyjna, która inicjuje jego „pole” członek:

import java.util.ArrayList; 
import java.util.Collection; 

public abstract class Foo { 
    private final Collection field = new ArrayList(); 

    protected Foo() { 
     System.out.println("In constructor"); 
    } 

    public boolean isNull(Object o) { 
     field.add(o); 

     return o == null; 
    } 

    abstract void someAbstractMethod(); 
} 

Tutaj klasa Test:

import org.junit.Assert; 
import org.junit.Test; 
import org.mockito.Mockito; 

public class FooTest { 
    @Test 
    public void testSomething() { 
     final Foo foo = Mockito.mock(Foo.class); 

     Mockito.when(foo.isNull(Mockito.anyObject())).thenCallRealMethod(); 

     Assert.assertFalse(foo.isNull("baaba")); 
    } 
} 

Kiedy test jest go uruchomić rzuca NPE ponieważ pole zmiennej” "nie jest zainicjowany!

Co robię źle?

+0

Korzystanie z http://docs.mockito.googlecode.com/hg/org/mockito/stubbing/OngoingStubbing.html#thenCallRealMethod%28%29 nie jest zalecane. Co chcesz przetestować? Jeśli jest to implementacja niektórych metod Foo, po prostu utwórz podklasę. Użyj Mockito, jeśli chcesz zweryfikować zachowanie lub wywołać metody standardowe. –

+0

Jak już powiedziałem do [@ david-wallace] (http://stackoverflow.com/users/1081110/david-wallace), chcę przetestować klasę abstrakcyjną. Moją intencją użycia makiety było zapobieganie błędowi kompilacji w przypadku zmiany klasy abstrakcyjnej lub jednego z jej interfejsów. – Pigelvy

Odpowiedz

4

Jest to oczekiwane zachowanie, gdy kpisz z czegoś, co stworzona instancja jest kompletną próbą, więc nie ma sensu inicjowanie pól jako domyślnego ustawienia .

Oprócz tego, pola mogą być inicjowane przez konstruktor w klasach betonowych lub abstrakcyjnych, ponieważ tworzenie makr omija konstruktora po prostu dlatego, że jest to makiety, jeszcze bardziej irracjonalne jest ich inicjowanie.

Próba wywoływania prawdziwej metody jest zwykle niewłaściwa podczas korzystania z mocks. Zamiast tego należy zaprzestać zachowania fałszywego.

Mockito.when(foo.isNull(Mockito.anyObject())).thenReturn(false); 
Assert.assertFalse(foo.isNull("baaba")); // assertion always passing 

nie wiem rzeczywisty przypadek użycia, ale może chcesz częściową makiety, z spy. Mimo że jest to nadal uważane za złą praktykę, ponieważ zazwyczaj oznacza to, że musisz zmienić kod, aby użyć kompozycji.

+0

Spodziewałem się, że Mockito zrobi coś, czego nie zaprojektowano. Jak omówiono z [@ David-Wallace] (http://stackoverflow.com/users/1081110/david-wallace), utworzę w moich testach sztuczną implementację, którą będę musiał zachować, jeśli metody zostaną dodane/usunięte. Thx – Pigelvy

+0

Czy jest to oczekiwane zachowanie także dla statycznych członków? Próbowałem i Mockito wymagało statycznych członków do zainicjowania, to powinno również pominąć tę inicjalizację? – dushyantashu

+0

@dushyantashu statyczne elementy są inicjowane przez program ładujący klasy po załadowaniu klasy. Mockito tego nie zmienia. – Brice

3

Wygląda na to, że kpisz z klasy, którą faktycznie próbujesz sprawdzić. To nie jest naprawdę kpina. Kpisz z zajęć, które nie mieszczą się w zakresie twojego testu, i pozostawiasz przedmiot, który testujesz, niezmieniony.

W takim przypadku powinieneś po prostu utworzyć Foo, z fałszywą implementacją someAbstractMethod i przetestować to bezpośrednio. Nie ma potrzeby na żadne kpiny, o ile widzę.

+0

Rzeczywiście, chcę kpić z klasy abstrakcyjnej, którą testuję, aby testy nie zakończyły się niepowodzeniem za każdym razem, gdy do tej klasy dodana została nowa abstrakcyjna metoda (lub jeden z jej interfejsów). Czy to naprawdę zła praktyka? – Pigelvy

+0

Nie jestem wystarczająco doświadczony, aby ustanowić prawo o tym, co jest "złą praktyką", a co nie. Ale wydaje się raczej, że używa się dłuta jako śrubokręta. To nie jest to, na co zostały zaprojektowane mocks.Mój instynkt polegałby wyłącznie na testowaniu własnej implementacji i dodawaniu nowych metod wszędzie tam, gdzie są potrzebne. Wydaje mi się, że zależy to od częstotliwości dodawania nowej metody abstrakcji do klasy - jeśli jest to częste zdarzenie, prawdopodobnie zastosowanie ma punkt Brice'a dotyczący refaktoryzacji kompozycji. Odpowiedź na twoje pytanie jest taka, że ​​Mockito nigdy nie było przeznaczone do ... –

+0

... inicjalizacji pól w swoich kpiach; teraz uzbrojeni w tę wiedzę, idźcie dalej i zróbcie swoje testy w dowolny sposób, który najbardziej ci odpowiada. –

Powiązane problemy