Jaka jest różnica między mock & stub?

Czytałem różne artykuły o wyśmiewaniu vs stubbing w testach, w tym kpiny Martina Fowlera nie są Stubami, ale nadal nie rozumiem różnicy.

Author: MattSayar, 2010-08-11

30 answers

Stub

Uważam, że największą różnicą jest to, że stub, który już napisałeś z góry określonym zachowaniem. Więc masz klasę, która implementuje zależność (klasa abstrakcyjna lub interfejs najprawdopodobniej), którą udajesz w celach testowych i metody byłyby po prostu stubowane z odpowiedziami zestawu. Nie zrobiliby nic wymyślnego, a ty już napisałbyś kod stubbed dla niego poza testem.

Mock

Makieta jest coś, co w ramach testu musisz skonfigurować zgodnie ze swoimi oczekiwaniami. Makieta nie jest skonfigurowana w określony sposób, więc masz kod, który robi to w swoim teście. Mocki w pewien sposób są określane w czasie wykonywania, ponieważ kod, który ustawia oczekiwania, musi zostać uruchomiony, zanim cokolwiek zrobi.

Różnica między Mocks i Stubs

Testy pisane mockami zwykle podążają za wzorcem initialize -> set expectations -> exercise -> verify do testów. Podczas gdy wcześniej napisany stub będzie następował po initialize -> exercise -> verify.

Podobieństwo między Mockami a Stubami

Celem obu jest wyeliminowanie testowania wszystkich zależności klasy lub funkcji, aby twoje testy były bardziej skoncentrowane i prostsze w tym, co próbują udowodnić.

 797
Author: Sean Copenhaver,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-04-03 20:08:12

Przedmowa

Istnieje kilka definicji obiektów, które nie są prawdziwe. Ogólny termin to Test double . Termin ten obejmuje: , fake, stub, mock .

Odniesienie

Według artykułu Martina Fowlera :

  • atrapy obiekty są przekazywane, ale nigdy w rzeczywistości nie są używane. Zwykle są one po prostu używane do wypełniania list parametrów.
  • Fake obiekty faktycznie mają działające implementacje, ale zwykle biorą jakiś skrót, który sprawia, że nie nadają się do produkcji (dobrym przykładem jest baza danych w pamięci).
  • Stuby zapewniają odpowiedzi w puszkach na połączenia wykonane podczas testu, zwykle nie reagują na nic poza tym, co jest zaprogramowane do testu. Stuby mogą również rejestrować informacje o połączeniach, takie jak stub bramki e-mail, który zapamiętuje wiadomości wysłane, a może tylko liczbę wiadomości wysłanych.
  • szyderstwa są tym, o czym tutaj mówimy: obiekty zaprogramowane z oczekiwaniami, które tworzą specyfikację wywołań, które mają otrzymać.

Style

Mocks vs Stubs = testy behawioralne vs testy państwowe

Zasada

Zgodnie z zasadą Test tylko jednej rzeczy na test , może być kilka punktów w jednym teście, ale ogólnie jest tylko jeden mock.

Cykl życia

Cykl życia badania z stubami:

  1. Setup-przygotowanie obiektu, który jest testowany i jego stubów.
  2. ćwiczenie-Przetestuj funkcjonalność.
  3. Verify state - use asserts to check object ' s state.
  4. Teardown-oczyść zasoby.

Cykl życia testu z mockami:

  1. Setup data-przygotuj testowany obiekt.
  2. Setup expectations - Przygotowanie oczekiwań w mocku, który jest używany przez primary obiekt.
  3. ćwiczenie-Przetestuj funkcjonalność.
  4. Verify expectations - Sprawdzenie, czy w mocku zostały wywołane poprawne metody.
  5. Verify state - use asserts to check object ' s state.
  6. Teardown-oczyść zasoby.

Podsumowanie

Zarówno testy mocks jak i stubs dają odpowiedź na pytanie: jaki jest wynik?

Testy z mockami są również zainteresowane: Jak wynik został / align = "left" /

 930
Author: Ryszard Dżegan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-17 07:35:49

Stub jest prostym fałszywym obiektem. To tylko sprawia, że test przebiega płynnie.
Makieta jest mądrzejsza. Sprawdzasz, czy twój test przechodzi przez to.

 401
Author: Arnis Lapsa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-05-27 12:08:45

Oto opis każdego z nich, po którym następuje próbka z prawdziwego świata.

  • Dummy - tylko fałszywe wartości, aby zaspokoić API.

    przykład: jeśli testujesz metodę klasy, która wymaga wielu obowiązkowych parametrów w konstruktorze, który nie ma wpływu na twój test, możesz tworzyć atrapy obiektów w celu utworzenia nowych instancji klasy.

  • Fake - create testowa Implementacja klasy, która może być zależna od jakiejś zewnętrznej infrastruktury. (Dobrą praktyką jest to, że twój test jednostkowy nie wchodzi w interakcję z zewnętrzną infrastrukturą.)

    przykład : Utwórz fałszywą implementację dostępu do bazy danych, zastąp ją kolekcją in-memory.

  • Stub - nadpisuje metody zwracające wartości zakodowane na twardo, zwane również state-based.

    przykład: twoja klasa testowa zależy od metody Calculate(), która zajmuje 5 minut. Zamiast czekać 5 minut można zastąpić jego rzeczywistą implementację stubem, który zwraca zakodowane na twardo wartości; zajmuje to tylko niewielką część czasu.

  • Mock - bardzo podobny do Stub, ale interaction-based zamiast oparty na stanie. Oznacza to, że nie oczekujesz od Mock zwrócenia jakiejś wartości, ale zakładasz, że wywołania metod są wykonywane w określonej kolejności.

    Przykład: testujesz klasę rejestracji użytkownika. Po wywołaniu Save powinien wywołać SendConfirmationEmail.

Stubs i {[10] } są w rzeczywistości podtypami Mock, oba zamieniają rzeczywistą implementację z implementacją testową, ale z różnych, specyficznych powodów.

 257
Author: Lev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-29 22:36:10

W codeschool.com Kurs, Rails Testing for Zombies , podają taką definicję pojęć:

Stub

Do zastąpienia metody kodem, który zwraca określony wynik.

Mock

Stub z twierdzeniem, że metoda zostanie wywołana.

Tak jak Sean Copenhaver opisał w swojej odpowiedzi, różnica polega na tym, że wyśmiewa ustawione oczekiwania (tzn. czyni twierdzenia, o tym, czy i w jaki sposób otrzymują called).

 182
Author: Dillon Kearns,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-07-04 22:32:54

Stuby nie obleją Twoich testów, mock może.

 147
Author: mk_,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-18 20:05:33

Czytając wszystkie powyższe wyjaśnienia, postaram się skondensować:

  • Stub : atrapa kodu, który pozwala uruchomić test, ale nie obchodzi cię, co się z nim stanie.
  • Mock: atrapa kodu, który weryfikujesz, jest poprawnie wywoływana jako część testu.
  • Spy : sztuczny fragment kodu, który przechwytuje niektóre połączenia do prawdziwego fragmentu kodu, pozwalając na weryfikację połączeń bez wymiany całego oryginalnego obiektu.
 49
Author: O'Rooney,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-07 01:57:14

Myślę, że najprostszą i jaśniejszą odpowiedź na to pytanie daje Roy Osherove w swojej książce sztuka testowania jednostkowego (strona 85)

Najprostszym sposobem, aby powiedzieć, że mamy do czynienia z punktem zwrotnym, jest zauważenie, że punkt nigdy nie może oblać testu. Testy są zawsze przeciwne klasa w trakcie testu.

Z drugiej strony, test użyje mock obiektu do sprawdzenia, czy test nie powiódł się czy nie. [...]

Ponownie, obiekt makiety jest obiektem, którego używamy, aby sprawdzić, czy test się nie powiódł, czy nie.

Oznacza to, że jeśli robisz twierdzenia przeciwko fałszywemu, oznacza to, że używasz fałszywego jako mock, jeśli używasz fałszywego tylko do uruchomienia testu bez twierdzenia na nim, używasz fałszywego jako stub.

 43
Author: Ghini Antonio,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-16 05:34:51

Makieta to tylko testowanie zachowania, upewnianie się, że wywołane są określone metody. Stub jest testowalną wersją (per se) określonego obiektu.

Jak to jabłkowy?

 30
Author: NebulaFox,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-10 21:08:06

Jeśli porównasz to z debugowaniem:

Stub jest jak upewnienie się, że metoda zwraca poprawną wartość

Mock jest jak faktycznie wchodzenie do metody i upewnianie się, że wszystko w środku jest poprawne przed zwróceniem prawidłowej wartości.

 23
Author: happygilmore,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-08 13:29:54

Być bardzo jasne i praktyczne:

Stub: klasa lub obiekt, który implementuje metody klasy / obiektu, które mają być sfałszowane i zwraca zawsze to, co chcesz.

Przykład w JavaScript:

var Stub = {
   method_a: function(param_a, param_b){
      return 'This is an static result';
   }
}

Mock: to samo co stub, ale dodaje logikę, która "weryfikuje" podczas wywoływania metody, więc możesz być pewien, że jakaś implementacja ją wywołuje.

Jak mówi @ mLevan wyobraź sobie jako przykład, że testujesz klasę rejestracji użytkownika. Po wywołaniu Save, powinno zadzwoń do SendConfirmationEmail.

Bardzo głupi przykład kodu:

var Mock = {
   calls: {
      method_a: 0
   }

   method_a: function(param_a, param_b){
     this.method_a++; 
     console.log('Mock.method_a its been called!');
   }
}
 22
Author: R01010010,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-20 12:08:53

Użycie mentalnego modelu naprawdę pomogło mi to zrozumieć, a nie wszystkie wyjaśnienia i artykuły, które nie do końca "zapadły się".

Wyobraź sobie, że Twoje dziecko ma szklany talerz na stole i zaczyna się nim bawić. Boisz się, że się złamie. Więc zamiast tego dajesz mu plastikową płytkę. To byłby Mock (to samo zachowanie, ten sam interfejs," łagodniejsza " implementacja).

Teraz powiedz, że nie masz plastikowej wymiany, więc wyjaśnij "jeśli nadal bawiąc się nim, pęknie!". To jest Stub, wcześniej podałeś predefiniowany stan.

A smoczek byłby widelcem, którego nawet nie użył... A Szpieg może być czymś w rodzaju wyjaśnienia, którego użyłeś, które zadziałało.

 21
Author: Moshisho,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-04-03 18:39:32

Myślę, że najważniejszą różnicą między nimi są ich intencje.

Spróbuję to wyjaśnić w Dlaczego stub vs. Dlaczego mock

Załóżmy, że piszę kod testowy dla publicznego kontrolera osi czasu mojego klienta mac Twittera

Oto kod próbki testowej

twitter_api.stub(:public_timeline).and_return(public_timeline_array)
client_ui.should_receive(:insert_timeline_above).with(public_timeline_array)
controller.refresh_public_timeline
  • STUB: połączenie sieciowe z twitter API jest bardzo wolne, co sprawia, że mój test powolny. Wiem, że zwróci timelines, więc zrobiłem stub symulujący HTTP twitter API, tak, że mój test uruchomi go bardzo szybko i mogę uruchomić test nawet jestem offline.
  • MOCK: nie napisałem jeszcze żadnej z moich metod UI i nie jestem pewien, jakie metody muszę napisać dla mojego obiektu ui. Mam nadzieję dowiedzieć się, jak mój kontroler będzie współpracował z moim obiektem ui, pisząc kod testowy.

Pisząc mock, odkrywasz zależność współpracy obiektów, sprawdzając, czy oczekiwania są spełnione, podczas gdy stub tylko symuluje zachowanie obiektu.

Proponuję przeczytać to artykuł jeśli chcesz dowiedzieć się więcej o mockach: http://jmock.org/oopsla2004.pdf

 19
Author: Joe Yang,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-14 17:10:26

Ten slajd bardzo dobrze wyjaśnia główne różnice.

Tutaj wpisz opis obrazka

[[0]} * z CSE 403 Wykład 16, University of Washington (slajd stworzony przez "Marty Stepp")
 19
Author: Aviram Fireberger,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-05 12:19:02

Pokaż Test podwojony:

  • Fake : podróbki to obiekty, które mają działające implementacje, ale nie takie same jak produkcyjne. , np. : implementacja w pamięci obiektu dostępu do danych lub repozytorium.
  • Stub : Stub jest obiektem, który przechowuje predefiniowane Dane i używa ich do odbierania wywołań podczas testów. takie jak : obiekt, który musi pobrać niektóre dane z bazy danych, aby odpowiedzieć na wywołanie metody.

  • Mocks : Mocki to obiekty rejestrujące odbierane połączenia. W testach możemy zweryfikować na Mockach, że wszystkie oczekiwane akcje zostały wykonane. takie jak : funkcjonalność, która wywołuje usługę wysyłania wiadomości e-mail. więcej po prostu sprawdź to .

 18
Author: Monsieur Aliréza,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-24 06:12:11

[[0]}podoba mi się Wyjaśnienie przedstawione przez Roy Osherove [Link Wideo] .

Każda utworzona klasa lub obiekt jest fałszywa. Jest to makieta, jeśli zweryfikować głosy przeciw: W przeciwnym razie jest to stub.

 14
Author: nitishagar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-20 06:59:07
  • Stubs vs. Mocks
    • Stuby
      1. podaj konkretne odpowiedzi na wywołania metod
        • ex: myStubbedService.getValues () po prostu zwraca ciąg znaków wymagany przez kod testowy
      2. używany przez testowany kod, aby go wyizolować
      3. nie można oblać testu
        • ex: myStubbedService.getValues () zwraca tylko wartość stubbed
      4. często wdrażaj metody abstrakcyjne
    • wyśmiewa
      1. "superset" stubów; może twierdzić, że niektóre metody są nazywane
        • ex: sprawdź, że myMockedService.getValues () jest wywołane tylko raz
      2. używany do testowania zachowania kodu w trakcie testu
      3. can fail test
        • ex: sprawdź, że myMockedService.getValues() została wywołana raz; weryfikacja nie powiodła się, ponieważ myMockedService.getValues() nie został wywołany przez mój testowany kod
      4. często wyśmiewa interfejsy
 14
Author: Relu Mesaros,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-02 12:35:06

Czytałem sztukę testowania jednostkowego i natknąłem się na następującą definicję:

A fake jest to ogólny termin, który może być używany do opisania wstępu lub mock obiektu (odręcznie lub w inny sposób), ponieważ oba wyglądają jak prawdziwy obiekt. To, czy podróbka jest wstępem, czy makietą, zależy od tego, jak zostanie użyta w bieżącym teście. jeśli jest używany do sprawdzania interakcji (twierdzenia przeciw), jest to mock object. W przeciwnym razie jest to stub.

 10
Author: Afonso Matos,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-11-07 13:57:52

A fake to ogólny termin, który może być użyty do opisania lub obiekt makiety (odręcznie lub inaczej), ponieważ oba wyglądają jak prawdziwy obiekt.

Czy fake to stub czy mock zależy od tego jak jest używany w obecny test. Jeśli jest używany do sprawdzania interakcji (twierdzenia przeciw), jest to mock object. W przeciwnym razie, to stub.

Fakes zapewnia sprawne działanie testu. Oznacza to, że czytelnik Twojego przyszłego testu zrozumie, co będzie zachowanie fałszywego obiektu, bez konieczności odczytywania jego kodu źródłowego(bez konieczności polegania na zewnętrznym zasobie).

Co oznacza płynny przebieg testu?
Przykład w poniższym kodzie:

 public void Analyze(string filename)
        {
            if(filename.Length<8)
            {
                try
                {
                    errorService.LogError("long file entered named:" + filename);
                }
                catch (Exception e)
                {
                    mailService.SendEMail("[email protected]", "ErrorOnWebService", "someerror");
                }
            }
        }
Chcesz przetestować mailService.Metoda SendEMail () , aby to zrobić musisz zasymulować wyjątek w swojej metodzie testowej, więc wystarczy utworzyć fałszywą klasę stub errorService, aby zasymulować ten wynik, wtedy twój kod testowy będzie mógł przetestować usługę mailService.SendEMail() metoda. Jak widzisz, musisz symulować wynik, który pochodzi z innej zewnętrznej klasy ErrorService zależności.
 9
Author: Mustafa Ekici,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-13 01:25:11

Prosto z papieru przykładowe role, Nie Obiekty, przez twórców jMock :

Stuby to atrapy implementacji kodu produkcyjnego, które zwracają puszki wyniki. Obiekty Mock działają jako stuby, ale zawierają również twierdzenia do instrument interakcji obiektu docelowego z jego sąsiadami.

Więc główne różnice to:

  • oczekiwania stawiane na stubach są zazwyczaj ogólne, podczas gdy oczekiwania stawiane na mockach mogą być bardziej "sprytne" (np. zwróć to przy pierwszym połączeniu, to przy drugim itd.).
  • stuby są używane głównie do ustawiania pośrednich wejść SUT , podczas gdy mocks mogą być używane do testowania zarówno pośrednich wejść, jak i pośrednich wyjść SUT.

Podsumowując, jednocześnie próbując rozwiać zamieszanie z artykułu Tytuł: kpiny to stuby, ale to nie tylko stuby .

 8
Author: Dimos,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-07 19:01:13

Natknąłem się na ciekawy artykuł Uncleboba The Little Mocker . Wyjaśnia całą terminologię w bardzo łatwy do zrozumienia sposób, więc jest przydatny dla początkujących. Artykuł Martina Fowlersa jest trudny do przeczytania, szczególnie dla początkujących, takich jak ja.

 7
Author: A.I,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-22 13:50:20

Wiele ważnych odpowiedzi tam, ale myślę, że warto wspomnieć o tej formie wujek bob: https://8thlight.com/blog/uncle-bob/2014/05/14/TheLittleMocker.html

Najlepsze wyjaśnienie z przykładami!

 6
Author: Kasper,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-18 15:01:46

Stub

A stub jest obiektem używanym do sfałszowania metody, która ma zaprogramowane zachowanie . Możesz użyć tej metody zamiast istniejącej metody, aby uniknąć niepożądanych efektów ubocznych (np. stub może wykonać Fałszywe wywołanie fetch, które zwróci zaprogramowaną odpowiedź bez konieczności wysyłania żądania do serwera).

Mock

A mock jest obiektem używanym do sfałszowania metody, która ma zaprogramowane zachowanie jak również zaprogramowane oczekiwania . Jeśli te oczekiwania nie zostaną spełnione, to mock spowoduje niepowodzenie testu (np. mock może wykonać Fałszywe wywołanie fetch, które zwróci zaprogramowaną odpowiedź bez rzeczywistego żądania do serwera, który spodziewałby się , np. pierwszy argument to http://localhost:3008/, w przeciwnym razie test by się nie powiódł.)

Różnica

W przeciwieństwie do mocks, stuby nie mają zaprogramowanych oczekiwań, które mogłyby zawieść twój test.

 6
Author: DeeFisher,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-09-09 10:25:07

Makieta jest zarówno obiektem technicznym jak i funkcjonalnym.

Makieta jest techniczna . Jest on rzeczywiście tworzony przez Bibliotekę szyderczą (EasyMock, JMockit i ostatnio Mockito są znane z nich) dzięki generowaniu kodu bajtowego.
Implementacja mocka jest generowana w sposób, w jaki możemyinstrument zwrócić określoną wartość, gdy wywołana jest metoda, ale także kilka innych rzeczy, takich jak sprawdzenie, czy metoda mocka została wywoływane z określonymi parametrami (strict check) lub dowolnymi parametrami (no strict check).

Tworzenie makiety:

@Mock Foo fooMock

Zapis zachowania:

when(fooMock.hello()).thenReturn("hello you!");

Weryfikacja wywołania:

verify(fooMock).hello()

Nie są to oczywiście naturalne sposoby tworzenia instancji/nadpisywania klasy / zachowania Foo. Dlatego odwołuję się do aspektu technicznego.

Ale mock jest również funkcjonalny ponieważ jest instancją klasy, którą musimy wyizolować od SUT. A z zapisanymi zachowaniami na nim, moglibyśmy użyć go w SUT w taki sam sposób, jak z stubem.


Stub jest po prostu obiektem funkcyjnym : jest to instancja klasy, którą musimy odizolować od SUT i to wszystko. Oznacza to, że zarówno Klasa stub, jak i wszystkie urządzenia behaviors potrzebne podczas naszych testów jednostkowych muszą być wyraźnie zdefiniowane.
Na przykład, aby stub hello() musiałby podklasować klasę Foo (lub zaimplementować jej interfejs ma) i do obejścia hello():

public class HelloStub extends Hello{    
  public String hello { 
      return "hello you!"; 
  }
}

Jeśli inny scenariusz testowy wymaga innego zwrotu wartości, prawdopodobnie będziemy musieli zdefiniować ogólny sposób ustawiania zwrotu:

public class HelloStub extends Hello{    
  public HelloStub(String helloReturn){
       this.helloReturn = helloReturn;
  }
  public String hello { 
      return helloReturn; 
  }
}

Inny scenariusz : gdybym miał metodę efektu ubocznego (bez powrotu) i sprawdziłbym, czy ta metoda została wywołana, prawdopodobnie powinienem dodać wartość logiczną lub licznik w klasie stub, aby policzyć, ile razy metoda została wywołana.


Wniosek

Stub wymaga często dużo narzutu/kodu do napisania do testu jednostkowego. Co mock uniemożliwia dzięki udostępnieniu funkcji nagrywania / weryfikacji po wyjęciu z pudełka.
Dlatego w dzisiejszych czasach podejście stub jest rzadko stosowane w praktyce wraz z pojawieniem się doskonałych bibliotek mock.


Jeśli chodzi o artykuł Martina Fowlera : nie uważam się za programistę "mockist", podczas gdy używam mocks i unikam stubów.
Ale używam mocka, gdy jest naprawdę wymagany (denerwujące zależności) i preferuję testowe krojenie i mini-testy integracyjne, gdy testuję klasę z zależnościami, które

 5
Author: davidxxx,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-07-23 06:30:33

Plus przydatne odpowiedzi, jeden z najbardziej mocnych punktów używania Moków niż pod

Jeśli współpracownik [od którego zależy główny kod] nie jest pod naszą kontrolą (np. z biblioteki innej firmy),
W tym przypadku, stub jest trudniejszy do napisania niż makieta.

 5
Author: ahmednabil88,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-02-15 00:53:54

Stub pomaga nam uruchomić test. Jak? Daje wartości, które pomagają uruchomić test. Wartości te same w sobie nie są prawdziwe i stworzyliśmy je tylko po to, aby uruchomić test. Na przykład tworzymy Hashmapę, aby dać nam wartości, które są podobne do wartości w tabeli bazy danych. Więc zamiast bezpośrednio wchodzić w interakcję z bazą danych, wchodzimy w interakcję z Hashmapą.

Mock jest fałszywym obiektem, który uruchamia test. gdzie umieszczamy

 4
Author: Harry,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-30 09:44:58

Zobacz poniżej przykład mocks vs stubs używając C# i MOQ framework. Moq nie ma specjalnego słowa kluczowego dla Stub, ale możesz użyć obiektu Mock do tworzenia stubów.

namespace UnitTestProject2
{
    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using Moq;
    [TestClass]
    public class UnitTest1
    {
        /// <summary>
        /// Test using Mock to Verify that GetNameWithPrefix method calls Repository GetName method "once" when Id is greater than Zero
        /// </summary>
        [TestMethod]
        public void GetNameWithPrefix_IdIsTwelve_GetNameCalledOnce()
        {
            // Arrange 
            var mockEntityRepository = new Mock<IEntityRepository>();
            mockEntityRepository.Setup(m => m.GetName(It.IsAny<int>()));

            var entity = new EntityClass(mockEntityRepository.Object);
            // Act 
            var name = entity.GetNameWithPrefix(12);
            // Assert
            mockEntityRepository.Verify(m => m.GetName(It.IsAny<int>()), Times.Once);
        }
        /// <summary>
        /// Test using Mock to Verify that GetNameWithPrefix method doesn't call Repository GetName method when Id is Zero
        /// </summary>
        [TestMethod]
        public void GetNameWithPrefix_IdIsZero_GetNameNeverCalled()
        {
            // Arrange 
            var mockEntityRepository = new Mock<IEntityRepository>();
            mockEntityRepository.Setup(m => m.GetName(It.IsAny<int>()));
            var entity = new EntityClass(mockEntityRepository.Object);
            // Act 
            var name = entity.GetNameWithPrefix(0);
            // Assert
            mockEntityRepository.Verify(m => m.GetName(It.IsAny<int>()), Times.Never);
        }
        /// <summary>
        /// Test using Stub to Verify that GetNameWithPrefix method returns Name with a Prefix
        /// </summary>
        [TestMethod]
        public void GetNameWithPrefix_IdIsTwelve_ReturnsNameWithPrefix()
        {
            // Arrange 
            var stubEntityRepository = new Mock<IEntityRepository>();
            stubEntityRepository.Setup(m => m.GetName(It.IsAny<int>()))
                .Returns("Stub");
            const string EXPECTED_NAME_WITH_PREFIX = "Mr. Stub";
            var entity = new EntityClass(stubEntityRepository.Object);
            // Act 
            var name = entity.GetNameWithPrefix(12);
            // Assert
            Assert.AreEqual(EXPECTED_NAME_WITH_PREFIX, name);
        }
    }
    public class EntityClass
    {
        private IEntityRepository _entityRepository;
        public EntityClass(IEntityRepository entityRepository)
        {
            this._entityRepository = entityRepository;
        }
        public string Name { get; set; }
        public string GetNameWithPrefix(int id)
        {
            string name = string.Empty;
            if (id > 0)
            {
                name = this._entityRepository.GetName(id);
            }
            return "Mr. " + name;
        }
    }
    public interface IEntityRepository
    {
        string GetName(int id);
    }
    public class EntityRepository:IEntityRepository
    {
        public string GetName(int id)
        {
            // Code to connect to DB and get name based on Id
            return "NameFromDb";
        }
    }
}
 4
Author: Adarsh Shah,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-01 16:51:14

Stub i Mock Testing point of view:

  • Stub jest atrapą implementacji wykonywaną przez użytkownika w static sposób, czyli w Stub zapisujący kod implementacji. Nie może więc obsługiwać definicji usługi i warunków dynamicznych, zwykle odbywa się to w JUnit framework bez użycia mocking framework.

  • Mock jest również implementacją atrapową, ale jej implementacja odbywa siędynamicznie w sposób za pomocą Wyśmiewanych frameworków, takich jak Mockito. Więc możemy obsługa warunku i definicji usługi jako sposób dynamiczny, tzn. mocki mogą być tworzone dynamicznie z kodu w czasie wykonywania. więc używając mocka możemy implementować Stuby dynamicznie.

 4
Author: Premraj,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-19 04:28:35

Użyłem przykładów Pythona w mojej odpowiedzi, aby zilustrować różnice.

Stub - Stub jest techniką tworzenia oprogramowania używaną do implementacji metod klas na początku cyklu rozwoju. Są one powszechnie używane jako symbole zastępcze dla implementacji znanego interfejsu, gdzie interfejs jest sfinalizowany lub znany, ale implementacja nie jest jeszcze znana lub sfinalizowana. Zaczynasz od stubs, co po prostu oznacza, że zapisujesz tylko definicję funkcji i zostaw kod na później. Zaletą jest to, że nie zapomnisz metod i możesz nadal myśleć o swoim projekcie, widząc go w kodzie. Możesz również zwrócić statyczną odpowiedź, aby odpowiedź mogła być natychmiast używana przez inne części kodu. Obiekty Stub zapewniają poprawną odpowiedź, ale jest ona statyczna bez względu na to, jakie dane wejściowe przekażesz, zawsze otrzymasz tę samą odpowiedź:

class Foo(object):
    def bar1(self):
        pass

    def bar2(self):
        #or ...
        raise NotImplementedError

    def bar3(self):
        #or return dummy data
        return "Dummy Data"

Mock obiekty są używane w przykładowych przypadkach testowych, które sprawdzają, że niektóre metody są wywoływane na tych obiektach. Mock objects to symulowane obiekty, które naśladują zachowanie rzeczywistych obiektów w kontrolowany sposób. Zazwyczaj tworzy się obiekt wzorcowy w celu przetestowania zachowania innego obiektu. Mocki pozwalają nam symulować zasoby, które są albo niedostępne, albo zbyt nieporęczne do testowania jednostkowego.

Mymodule.py:

import os
import os.path

def rm(filename):
    if os.path.isfile(filename):
        os.remove(filename)

Test.py:

from mymodule import rm
import mock
import unittest

class RmTestCase(unittest.TestCase):
    @mock.patch('mymodule.os')
    def test_rm(self, mock_os):
        rm("any path")
        # test that rm called os.remove with the right parameters
        mock_os.remove.assert_called_with("any path")

if __name__ == '__main__':
    unittest.main()

Jest to bardzo prosty przykład, który uruchamia rm i potwierdza parametr, z którym został wywołany. Możesz użyć mocka z obiekty nie tylko działają jak pokazano tutaj, ale można również zwrócić wartość, aby obiekt makiety mógł zostać użyty do zastąpienia elementu wejściowego do testowania.

Więcej na unittest.mock , uwaga w Pythonie 2.x mock nie jest częścią unittest, ale jest modułem do pobrania, który można pobrać za pomocą pip (pip install mock).

Czytałem też" the Art of Unit Testing "Roya Osherove' a i myślę, że byłoby świetnie, gdyby podobna książka została napisana przy użyciu Pythona i Pythona. Jeśli ktoś wie o taką książkę Proszę podzielić się. Pozdrawiam :)

 2
Author: radtek,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-13 19:35:39

Stub jest fałszywym obiektem zbudowanym do celów testowych. Mock jest stubem, który rejestruje, czy oczekiwane wywołania rzeczywiście wystąpiły.

 2
Author: simon.denel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-21 18:56:48