Pytanie Jak przeprowadzić logikę zwrotną testu jednostkowego?


Bardziej kompletne pytanie brzmi: biorąc pod uwagę zależność, która oczekuje wywołania zwrotnego jako parametru, jak napisać test jednostkowy, który obejmuje logikę zwrotną i wciąż udaje się wykpić zależność?

public class DoStuff {
    public void runThis(Runnable callback) {
        // call callback
    }
}

public class ClassUnderTest {
    private DoStuff stuffToDo;

    public void methodUnderTest() {
        this.stuffToDo.runThis(/*a runnable with some logic*/)
    }
}

W powyższym przykładzie kpiłbym stuffToDo ponieważ powinienem zweryfikować połączenia i fałszywe wyniki wywołań metod. Jednak kpiny runThis powoduje, że logika wywołania zwrotnego nie jest testowana. Ponadto logika wywołania zwrotnego wydaje się być prywatna, więc nie spodziewam się, że przetestuję ją bezpośrednio; może to z mojej strony nieporozumienie.

Ponieważ wywołania zwrotne są używane dość ekstensywnie, spodziewam się, że istnieje wspólna metoda testowania ich, ale nie znalazłem tego.


11
2017-08-22 13:16


pochodzenie


Czy oddzwanianie musi być tylko testowane w tym kontekście? Jeśli tak, to dlaczego nie po prostu pisać testy dla różnych zwrotów, które planujesz przejść, które wyrażają oczekiwanie na ich wyniki? Czy czegoś brakuje? - Jonah
Czy próbowałeś używać CountDownLatch jak w tym przykładzie: stackoverflow.com/a/3802487/2301224 - Baker


Odpowiedzi:


Nie możesz w jednym teście. Jeśli wyśmiewasz coś, jego wyśmiewali się, co oznacza, że ​​może jedynie weryfikować argumenty i symulować zwracane wartości (konfigurowane w teście).

W rzeczy samej, cały punkt kpiny z czegoś polega na sprawdzeniu, co używa próbnego w izolacji. Jeśli chcesz test jednostkowy DoStuff, nie musisz martwić się o użycie jakiejś implementacji wywołania zwrotnego, która może działać lub nie. Kpisz z callbacka, więc nie musisz się tym martwić.

Nadal możesz mieć dobre testy, testując kod zwrotny w izolacji, i testowanie użytkownika oddzwaniania w izolacji (przy pomocy próbnego wywołania zwrotnego) i być może poprzez rzucenie testu integracyjnego na dobry środek, w którym używa się w pełni skonfigurowanego komponentu jako całości.


10
2017-08-22 13:31





Tutaj zasadniczo chcesz przetestować klasę Robić coś. Oznacza to, że musisz sprawdzić wszystkie metody w DoStuffu, prawda ?. Tak więc w tym przypadku, zamiast kpić, trzeba to zrobić rzeczy do zrobienia samo, wstrzykiwać wyśmiewany Runnable w stuffToDo. A następnie sprawdź, czy twój runnable został pomyślnie wykonany, czy nie.

Ale jeśli masz inne funkcje w klasie, możesz mieć osobny test i wyśmiewać je.


1
2017-08-22 13:32



Chcę przetestować ClassUnderTest, który przyjmuje DoStuff jako zależność. - Andrew White


W twoim konkretnym przypadku wygląda na to, że już testowałeś DoStuff (lub nie obchodzi już to, ponieważ jest wyśmiewany), a teraz są specyficzne testy jednostkowe Runnable zaprojektowałeś. W tym przypadku, callback brzmi jak dokładnie to, co chcesz przetestować, w taki sam sposób, jak ktoś może chcieć bezpośrednio przetestować strategię bazy danych lub strategię w pamięci bezpośrednio.

Jeśli to właśnie próbujesz, możesz przetestować go w czarnej skrzynce, wykonując ją ClassUnderTest najlepiej jak potrafisz. Lub możesz utworzyć uprząż testową na swoim konkretnym runnie. Jeśli zwalniasz ten kod i nie chcesz, aby uprzęże testowe były osiągalne, możesz uczynić metody przewodów uprzęży prywatnymi i udostępnić szczegóły w swoim zespole testowym.

Popatrz tutaj aby uzyskać informacje o tym, jak tworzyć zestawy przyjaciół. Zazwyczaj podpisuję kod testowy jednostki, aby nie musiałem go tłumić za pomocą kompilatora wiersza poleceń. Przypuszczam, że zależy to od środowiska twojej kompilacji.


0
2017-08-22 13:42



Nie, ClassUnderTest jest klasą do przetestowania. Kpię z DoStuffa. - Andrew White
Zmodyfikowałem nazwę klasy, aby to odzwierciedlić. To nie ma wpływu na odpowiedź. - Michael Hays


Co powiesz na fałszywy DoStuff, który tylko bezwarunkowo wywołuje Runnable?

Następnie wyczuwasz efekty - zmiany, które należy zaobserwować, jeśli zostało wykonane wywołanie zwrotne.


0
2017-08-23 05:40





Jeśli używasz EasyMock, możesz użyć andStubAnswer aby wywołać działanie.

doSomethingMock.runThis(runnable);
expectLastCall().andStubAnswer(new IAnserable<Void>() {
   Runnable runnable = (Runnable)getCurrentArguments()[0];
   runnable.run();
   return null;
});

Wyobrażam sobie, że inne szydercze ramy zawierają coś podobnego.


0
2017-08-22 19:45