Jaka jest różnica między udawaniem, wyśmiewaniem i karczowaniem?

705

Wiem, jak używać tych terminów, ale zastanawiam się, czy nie są akceptowane definicje udaje , szydząc i stubbing dla testów jednostkowych? Jak je zdefiniujesz dla swoich testów? Opisz sytuacje, w których możesz ich użyć.

Oto jak ich używam:

Fake : klasa, która implementuje interfejs, ale zawiera stałe dane i brak logiki. Zwraca po prostu „dobre” lub „złe” dane w zależności od implementacji.

Mock : klasa, która implementuje interfejs i pozwala na dynamiczne ustawianie wartości zwracanych / wyjątków do odrzucenia z poszczególnych metod i zapewnia możliwość sprawdzenia, czy określone metody zostały wywołane / nie zostały wywołane.

Stub : Niby klasa pozorna, z tym wyjątkiem, że nie zapewnia możliwości sprawdzenia, czy metody zostały wywołane / nie zostały wywołane.

Makiety i kody pośredniczące mogą być generowane ręcznie lub generowane przez ramy próbne. Fałszywe klasy są generowane ręcznie. Używam próbnych przede wszystkim do weryfikacji interakcji między moją klasą a klasami zależnymi. Używam kodów pośredniczących po zweryfikowaniu interakcji i testowaniu alternatywnych ścieżek za pomocą mojego kodu. Używam fałszywych klas przede wszystkim do wyodrębnienia zależności danych lub gdy próby / kody pośredniczące są zbyt uciążliwe, aby je konfigurować za każdym razem.

tvanfosson
źródło
6
Cóż, w zasadzie powiedziałeś to wszystko w swoim „pytaniu” :) Myślę, że są to dość dobrze przyjęte definicje tych terminów
Eran Galperin
2
Definicja fałszywej Wikipedii różni się od tej, twierdząc, że fałszywa „jest używana jako prostsza implementacja, np. Użycie bazy danych w pamięci w testach zamiast rzeczywistego dostępu do bazy danych)” Patrz en.wikipedia.org/wiki/Test_double
zumalifeguard
2
Wiele się nauczyłem z następującego zasobu, z doskonałym wyjaśnieniem Roberta C. Martina (wujek Bob): Mały kpina na blogu Clean Code . Wyjaśnia różnice i subtelności manekinów, dublowania testowe, odcinki, szpiedzy, (prawdziwe) kpiny i podróbki. Wspomina także Martina Fowlera i wyjaśnia historię testów oprogramowania.
Erik
testing.googleblog.com/2013/07/… (krótkie jednostronicowe streszczenie).
ShreevatsaR
Oto moje wyjaśnienie: Test Doubles: Fakes, Stubs and Mocks (post na blogu z przykładami)
michal-lipski

Odpowiedzi:

548

Możesz uzyskać informacje:

Od Martina Fowlera o Mock and Stub

Fałszywe obiekty faktycznie mają działające implementacje, ale zwykle wymagają skrótu, który sprawia, że ​​nie nadają się do produkcji

Stuby zapewniają konserwowane odpowiedzi na wywołania wykonane podczas testu, zwykle nie reagując wcale na nic poza tym, co jest zaprogramowane na test. Stuby mogą również rejestrować informacje o połączeniach, takie jak kod pośredniczący bramy e-mail, który zapamiętuje wiadomości, które „wysłał”, a może tylko liczbę wiadomości, które „wysłał”.

Mocks są tym, co mówimy o tutaj: Przedmioty z zaprogramowanymi oczekiwań stanowiących specyfikację połączeń oczekuje oni otrzymać.

Z Xunitpattern :

Fałszywe : Pozyskujemy lub budujemy bardzo lekką implementację tej samej funkcjonalności, jaką zapewnia komponent, od którego zależy SUT, i instruujemy, aby używał SUT zamiast rzeczywistej.

Stub : Ta implementacja jest skonfigurowana do reagowania na wywołania z SUT z wartościami (lub wyjątkami), które wykonają nieprzetestowany kod (patrz Błędy produkcyjne na stronie X) w SUT. Kluczowym wskazaniem do użycia testu Stub jest posiadanie nieprzetestowanego kodu spowodowanego niemożnością kontrolowania pośrednich danych wejściowych SUT

Mock Object, który implementuje ten sam interfejs co obiekt, od którego zależy SUT (System Under Test). Możemy użyć fałszywego obiektu jako punktu obserwacyjnego, gdy potrzebujemy wykonać weryfikację zachowania, aby uniknąć posiadania niesprawdzonego wymagania (patrz Błędy produkcyjne na stronie X) spowodowanego niemożnością zaobserwowania skutków ubocznych wywoływania metod w SUT.

Osobiście

Staram się uprościć, używając: Mock and Stub. Używam Mock, gdy jest to obiekt, który zwraca wartość ustawioną dla testowanej klasy. Używam Stuba, aby naśladować testowaną klasę Interface lub Abstract. W rzeczywistości nie ma znaczenia, jak to nazwiesz, wszystkie są klasami, które nie są używane w produkcji i są używane jako klasy narzędzi do testowania.

Patrick Desjardins
źródło
9
Wydaje mi się, że definicje Stub i Fake są odwrócone w cytacie xUnitPattern w porównaniu z cytatem Martina Fowlera. Ponadto definicje Stub i Fake Martina Fowlera są odwrócone w porównaniu z definicjami zawartymi w pierwotnym pytaniu tvanfosson. W rzeczywistości, czy są jakieś ogólnie przyjęte definicje tych dwóch terminów, czy tylko zależy to od tego, z kim rozmawiasz?
Simon Tewsi
3
+1 za „Staram się uprościć, używając: Mock and Stub”. To świetny pomysł!
Brad Cupit
4
Nie widzę, jak używanie tylko Mock and Stub to świetny pomysł. Każde podwójne badanie ma swoje cele, a tym samym swoje zastosowania.
Hector Ordonez
1
Nie widzę różnicy między Fake a Mock w definicji MF.
IdontCareAboutReputationPoints
2
@MusuNaji: W definicji MF nie ma żadnych „oczekiwań” w odniesieniu do rozmowy dla fałszywego, poza tym, że ma implementację interfejsu. Z drugiej strony Mock będzie kwestionowany (czy ta metoda została nazwana?).
dbalakirev
205

Stub - obiekt, który zapewnia predefiniowane odpowiedzi na wywołania metod.

Mock - obiekt, na którym stawiasz oczekiwania.

Fake - obiekt o ograniczonych możliwościach (do celów testowych), np. Fałszywy serwis internetowy.

Test Double to ogólny termin na kody pośredniczące, kpiny i podróbki. Ale nieformalnie często słyszysz, jak ludzie nazywają ich kpiną.

Mikrofon
źródło
4
Czy ktoś mógłby mi wyjaśnić i zdefiniować, co to jest „odpowiedź w puszce” w tym kontekście?
MasterMastic 24.01.2013
14
Wartość jawna, a nie wartość obliczana.
Mike
Wreszcie! Niektóre definicje, które mogę zrozumieć! Opierając się na tych definicjach, googletest (gtest) / googlemock (gmock) pozwala, aby wyśmiewane obiekty były również kodami pośredniczącymi , ponieważ można tworzyć EXPECT_CALL()s na pozorowanej metodzie, która wymusza określone wyniki na podstawie określonych danych wejściowych, przy użyciu typu .WillOnce(Invoke(my_func_or_lambda_func))(lub z .WillRepeatedly()) składnia dołączona do EXPECT_CALL(). Niektóre przykłady użycia Invoke()można zobaczyć w innym kontekście u dołu mojej długiej odpowiedzi tutaj: stackoverflow.com/a/60905880/4561887 .
Gabriel Staples
Dokumentacja Gmock na Invoke()jest tutaj: github.com/google/googletest/blob/master/googlemock/docs/… . W każdym razie, wniosek jest taki: Google mock (gmock) pozwala na łatwe tworzenie zarówno mocks i odcinki , choć większość mocks nie są odcinki.
Gabriel Staples
Egzaminy są nadzbiorem Stubów, nadal mogą zwracać predefiniowane odpowiedzi, ale także pozwalają programistom na ustalanie oczekiwań. IMO niektóre biblioteki tam rozmazują linie wszystkich testowych manekinów.
Łukasza
94

Dziwi mnie, że pytanie to istniało już od tak dawna i nikt jak dotąd nie udzielił odpowiedzi w oparciu o „The Art of Unit Testing” Roya Osherove'a .

W „3.1 Wprowadzenie kodów pośredniczących” kod pośredniczący definiuje się jako:

Kod pośredniczący jest kontrolowanym zamiennikiem istniejącej zależności (lub współpracownika) w systemie. Korzystając z kodu pośredniczącego, możesz przetestować kod bez bezpośredniego radzenia sobie z zależnością.

I definiuje różnicę między kodami pośredniczącymi a próbnymi jako:

Najważniejszą rzeczą, o której należy pamiętać w przypadku makiet kontra odcinków, jest to, że odcinki są jak odcinki odcinków, ale zapewnia się je przeciwko próbnemu obiektowi, a nie odcinają się od odcinka zwrotnego.

Fałszywe to tylko nazwa używana zarówno dla kodów pośredniczących, jak i próbnych. Na przykład, gdy nie obchodzi Cię rozróżnienie między skrótami a próbami.

Sposób, w jaki Osherove odróżnia kody pośredniczące od próbnych, oznacza, że ​​każda klasa używana jako podróbka do testów może być zarówno pośrednicząca, jak i próbna. To, co jest dla konkretnego testu, zależy całkowicie od tego, jak wypisujesz czeki w teście.

  • Kiedy twój test sprawdza wartości w testowanej klasie lub właściwie gdziekolwiek poza fałszywką, fałszywka była używana jako kod pośredniczący. Po prostu podał wartości, których ma użyć testowana klasa, albo bezpośrednio przez wartości zwrócone przez wywołania do niej, albo pośrednio poprzez wywołanie efektów ubocznych (w niektórych stanach) w wyniku wywołania tego wywołania.
  • Kiedy test sprawdza wartości podróbki, był używany jako próbka.

Przykład testu, w którym klasa FakeX jest używana jako kod pośredniczący:

const pleaseReturn5 = 5;
var fake = new FakeX(pleaseReturn5);
var cut = new ClassUnderTest(fake);

cut.SquareIt;

Assert.AreEqual(25, cut.SomeProperty);

fakeInstancji służy jako odgałęzienie, ponieważ Assertnie korzysta fakew ogóle.

Przykład testu, w którym klasa testowa X jest używana jako próbka:

const pleaseReturn5 = 5;
var fake = new FakeX(pleaseReturn5);
var cut = new ClassUnderTest(fake);

cut.SquareIt;

Assert.AreEqual(25, fake.SomeProperty);

W tym przypadku Assertsprawdza wartość fake, co czyni z tego fałszywego makieta.

Oczywiście te przykłady są wysoce wymyślone, ale widzę wielką zasługę w tym rozróżnieniu. Uświadamia ci, w jaki sposób testujesz swoje rzeczy i gdzie są zależności w teście.

Zgadzam się z tym Osherove

z czystego punktu widzenia łatwości konserwacji, w moich testach używanie próbnych elementów stwarza więcej problemów niż ich nieużywanie. To było moje doświadczenie, ale zawsze uczę się czegoś nowego.

Przeciwstawianie się podróbkom jest czymś, czego naprawdę chcesz uniknąć, ponieważ bardzo uzależnia twoje testy od implementacji klasy, która w ogóle nie jest testowana. Co oznacza, że ​​testy dla klasy ActualClassUnderTestmogą zacząć się rozpadać, ponieważ zmieniono implementację ClassUsedAsMock. I to wywołuje dla mnie nieprzyjemny zapach. Testy ActualClassUnderTestnajlepiej przerwać tylko po ActualClassUnderTestzmianie.

Zdaję sobie sprawę, że pisanie oświadczeń przeciwko podróbkom jest powszechną praktyką, szczególnie gdy jesteś mockistowskim typem subskrybenta TDD. Wydaje mi się, że jestem zdecydowanie z Martinem Fowlerem w obozie klasycystycznym (patrz Mocky nie są skrótami ) i podobnie jak Osherove unikają testowania interakcji (co można zrobić tylko poprzez walkę z podróbką).

Aby przeczytać, dlaczego należy unikać drwin, jak zdefiniowano tutaj, przejdź do Google dla „fowler mockist classicist”. Znajdziesz mnóstwo opinii.

Marjan Venema
źródło
30

Jak wspomniano w najczęściej głosowanej odpowiedzi, Martin Fowler omawia te rozróżnienia w Mocks Aren't Stubs , a w szczególności w podtytule The Difference Between Mocks and Stubs , więc przeczytaj ten artykuł.

Zamiast skupiać się na jak te rzeczy są różne, myślę, że to bardziej skupić się na oświecenie dlaczego są różne koncepcje. Każdy istnieje w innym celu.

Podróbki

Fałszywy jest implementacją, która zachowuje się w sposób „naturalny”, ale nie jest „prawdziwy”. Są to rozmyte pojęcia, więc różni ludzie rozumieją, co czyni je fałszywymi.

Jednym z przykładów podróbki jest baza danych w pamięci (np. Używanie sqlite ze :memory:sklepem). Nigdy nie użyłbyś tego do produkcji (ponieważ dane nie są utrwalane), ale jest to całkowicie wystarczające jako baza danych do użycia w środowisku testowym. Jest również znacznie lżejszy niż „prawdziwa” baza danych.

Jako inny przykład, być może używasz jakiegoś magazynu obiektów (np. Amazon S3) w produkcji, ale w teście możesz po prostu zapisać obiekty do plików na dysku; wówczas implementacja „zapisz na dysku” byłaby fałszywa. (Lub możesz nawet sfałszować operację „zapisz na dysku”, używając zamiast tego systemu plików w pamięci).

Jako trzeci przykład wyobraź sobie obiekt, który udostępnia interfejs API pamięci podręcznej; obiekt, który implementuje poprawny interfejs, ale który po prostu nie wykonuje buforowania, ale zawsze zwraca brak pamięci podręcznej, byłby rodzajem fałszywki.

Celem podróbki nie jest wpływanie na zachowanie testowanego systemu , ale uproszczenie implementacji testu (poprzez usunięcie zbędnych lub ciężkich zależności).

Stuby

Stub jest implementacją, która zachowuje się „nienaturalnie”. Jest wstępnie skonfigurowany (zwykle przez konfigurację testową), aby reagować na określone dane wejściowe za pomocą określonych danych wyjściowych.

Celem kodu pośredniczącego jest doprowadzenie testowanego systemu do określonego stanu. Na przykład, jeśli piszesz test na kod, który wchodzi w interakcję z interfejsem API REST, możesz zlikwidować interfejs API REST za pomocą interfejsu API, który zawsze zwraca odpowiedź standardową lub który odpowiada na żądanie interfejsu API z określonym błędem. W ten sposób możesz napisać testy, które zawierają stwierdzenia o tym, jak system reaguje na te stany; na przykład testowanie odpowiedzi uzyskiwanej przez użytkowników, jeśli interfejs API zwraca błąd 404.

Kod pośredniczący jest zwykle implementowany, aby reagować tylko na dokładne interakcje, na które kazałeś mu odpowiedzieć. Ale kluczową cechą, która sprawia, że ​​coś jest odgałęzieniem, jest jego cel : w odgałęzieniu chodzi o skonfigurowanie twojego przypadku testowego.

Makiety

Makiety jest podobna do zalążek, ale z weryfikacji dodanej. Celem mock jest, aby twierdzenia dotyczące konfiguracji urządzeń w ramach testu w interakcję z uzależnienia .

Na przykład, jeśli piszesz test systemu, który przesyła pliki do strony internetowej, możesz zbudować próbkę, która akceptuje plik i której możesz użyć, aby potwierdzić, że przesłany plik jest poprawny. Lub, na mniejszą skalę, często używa się makiety obiektu, aby sprawdzić, czy testowany system wywołuje określone metody kpionego obiektu.

Próbki są powiązane z testowaniem interakcji , które jest specyficzną metodologią testowania. Ludzie, którzy wolą testować stan systemu niż interakcje systemowe, będą używać próbnych , jeśli w ogóle, oszczędnie.

Test podwaja się

Podróbki, odcinki i makiety należą do kategorii podwójnych testów . Podwójny test to dowolny obiekt lub system używany w teście zamiast czegoś innego. Większość zautomatyzowanych testów oprogramowania wymaga użycia podwójnych testów. Niektóre inne rodzaje deblu testowych obejmują wartości nieużywane , szpiegów i I / O blackholes .

Daniel Pryden
źródło
11

Aby zilustrować użycie kodów pośredniczących i próbnych, chciałbym również dołączyć przykład oparty na „ The Art of Unit Testing ” Roya Osherove'a .

Wyobraź sobie, że mamy aplikację LogAnalyzer, która ma wyłączną funkcję drukowania dzienników. Musi nie tylko rozmawiać z usługą internetową, ale jeśli usługa internetowa zgłosi błąd, LogAnalyzer musi zalogować błąd do innej zależności zewnętrznej, wysyłając go e-mailem do administratora usługi internetowej.

Oto logika, którą chcielibyśmy przetestować w LogAnalyzer:

if(fileName.Length<8)
{
 try
  {
    service.LogError("Filename too short:" + fileName);
  }
 catch (Exception e)
  {
    email.SendEmail("a","subject",e.Message);
  }
}

Jak sprawdzić, czy LogAnalyzer poprawnie wywołuje usługę e-mail, gdy usługa sieciowa zgłasza wyjątek? Oto pytania, przed którymi stoimy:

  • Jak możemy zastąpić serwis internetowy?

  • Jak możemy zasymulować wyjątek od usługi internetowej, abyśmy mogli przetestować połączenie z usługą e-mail?

  • Skąd będziemy wiedzieć, że usługa e-mail została poprawnie lub w ogóle wywołana?

Pierwsze dwa pytania możemy rozwiązać, korzystając z kodu pośredniczącego dla usługi sieci Web . Aby rozwiązać trzeci problem, możemy użyć fałszywego obiektu dla usługi e-mail .

Fałszywy to ogólny termin, którego można użyć do opisania kodu pośredniczącego lub próbnego. W naszym teście otrzymamy dwa fałszywe. Jednym z nich będzie próbna usługa e-mail, której użyjemy do zweryfikowania, czy do usługi e-mail wysłano prawidłowe parametry. Drugim będzie kod pośredniczący, którego użyjemy do symulacji wyjątku zgłoszonego przez serwis internetowy. Jest to zalążek, ponieważ nie będziemy używać fałszywej usługi sieci Web do weryfikacji wyniku testu, a jedynie do upewnienia się, że test działa poprawnie. Usługa e-mail jest fałszywą, ponieważ twierdzimy, że została poprawnie wywołana.

[TestFixture]
public class LogAnalyzer2Tests
{
[Test]
 public void Analyze_WebServiceThrows_SendsEmail()
 {
   StubService stubService = new StubService();
   stubService.ToThrow= new Exception("fake exception");
   MockEmailService mockEmail = new MockEmailService();

   LogAnalyzer2 log = new LogAnalyzer2();
   log.Service = stubService
   log.Email=mockEmail;
   string tooShortFileName="abc.ext";
   log.Analyze(tooShortFileName);

   Assert.AreEqual("a",mockEmail.To); //MOCKING USED
   Assert.AreEqual("fake exception",mockEmail.Body); //MOCKING USED
   Assert.AreEqual("subject",mockEmail.Subject);
 }
}
nanospeck
źródło
9

tym, czego dochodzić na nim, nazywa się mock obiektu i wszystko inne, co tylko pomógł rozruch próbny, jest en .

Arezoo Bagherzadi
źródło
1
podczas gdy inne odpowiedzi mają wiele szczegółów i są naprawdę dobre. ten sprawia, że ​​różnica jest tak jasna i łatwa, że ​​trudno nie głosować pozytywnie. gj!
Mario Garcia,
6

Chodzi o to, aby testy były ekspresyjne. Ustawiam oczekiwania na próbę, jeśli chcę, aby test opisał związek między dwoma obiektami. Zwracam wartości zwracane, jeśli konfiguruję obiekt pomocniczy, aby uzyskać interesujące zachowanie w teście.

Steve Freeman
źródło
6

Jeśli znasz Arrange-Act-Assert, jednym ze sposobów wyjaśnienia różnicy między kodem pośredniczącym a próbnym, które mogą być dla Ciebie przydatne, jest to, że kody pośredniczące należą do sekcji arrange, ponieważ służą one do ustawiania stanu wejściowego, a symulacje należą do sekcja potwierdzenia, ponieważ służą one do potwierdzenia wyników.

Manekiny nic nie robią. Służą one wyłącznie do wypełniania list parametrów, aby nie występowały błędy niezdefiniowane lub zerowe. Istnieją również po to, by spełniać funkcję sprawdzania typów w ściśle wpisywanych językach, dzięki czemu możesz mieć możliwość kompilacji i uruchamiania.

Sammi
źródło
3

Stub, podróbki i makiety mają różne znaczenie w różnych źródłach. Sugeruję wprowadzenie wewnętrznych warunków zespołu i uzgodnienie ich znaczenia.

Myślę, że ważne jest rozróżnienie między dwoma podejściami: - walidacja zachowania (implikuje zastąpienie zachowania) - walidacja stanu końcowego (imitacja zachowania)

W przypadku błędu rozważ wysłanie wiadomości e-mail. Kiedy robi poprawności zachowań - sprawdzić tę metodę Sendz IEmailSenderzostała wykonana jednorazowo. I musisz emulować wynik tej metody, zwróć identyfikator wysłanej wiadomości. Więc mówicie: „Spodziewam się tegoSend to zostanie wywołane. I po prostu zwrócę fałszywy (lub losowy) identyfikator dla każdego połączenia” . Oto sprawdzanie poprawności zachowania: emailSender.Expect(es=>es.Send(anyThing)).Return((subject,body) => "dummyId")

Podczas sprawdzania stanu konieczne będzie utworzenie TestEmailSendertego narzędzia IEmailSender. I zaimplementuj Sendmetodę - zapisując dane wejściowe do jakiejś struktury danych, która będzie używana do przyszłej weryfikacji stanu, takiej jak tablica niektórych obiektów, SentEmailsa następnie przetestujesz, czy to sprawdziszSentEmails zawiera oczekiwany e-mail. To jest sprawdzanie stanu: Assert.AreEqual(1, emailSender.SentEmails.Count)

Z moich odczytów zrozumiałem, że walidacja zachowań zwykle nazywana jest próbą . I sprawdzanie stanu zwykle zwane skrótami lub podróbkami .

Marat Gallyamov
źródło
Naprawdę bardzo szczegółowe i wyraźne określenie.
shyam sundar singh tomar
2

stub i fake są obiektami, ponieważ mogą zmieniać swoją odpowiedź w zależności od parametrów wejściowych. główna różnica między nimi polega na tym, że Fake jest bliższy implementacji w świecie rzeczywistym niż odgałęzienie. Stuby zawierają zasadniczo zakodowane odpowiedzi na oczekiwane żądanie. Zobaczmy przykład:

public class MyUnitTest {

 @Test
 public void testConcatenate() {
  StubDependency stubDependency = new StubDependency();
  int result = stubDependency.toNumber("one", "two");
  assertEquals("onetwo", result);
 }
}

public class StubDependency() {
 public int toNumber(string param) {
  if (param == “one”) {
   return 1;
  }
  if (param == “two”) {
   return 2;
  }
 }
}

Mock to krok w górę od podróbek i króćców. Makiety zapewniają taką samą funkcjonalność jak kody pośredniczące, ale są bardziej złożone. Mogą mieć zdefiniowane dla nich reguły określające, w jakiej kolejności muszą być wywoływane metody interfejsu API. Większość próbnych może śledzić, ile razy została wywołana metoda i może reagować na podstawie tych informacji. Egzaminy na ogół znają kontekst każdego połączenia i mogą reagować inaczej w różnych sytuacjach. Z tego powodu drwiny wymagają pewnej wiedzy na temat klasy, z której drwią. kodów pośredniczących zazwyczaj nie można śledzić, ile razy została wywołana metoda lub w jakiej kolejności została wywołana sekwencja metod. Makieta wygląda jak:

public class MockADependency {

 private int ShouldCallTwice;
 private boolean ShouldCallAtEnd;
 private boolean ShouldCallFirst;

 public int StringToInteger(String s) {
  if (s == "abc") {
   return 1;
  }
  if (s == "xyz") {
   return 2;
  }
  return 0;
 }

 public void ShouldCallFirst() {
  if ((ShouldCallTwice > 0) || ShouldCallAtEnd)
   throw new AssertionException("ShouldCallFirst not first thod called");
  ShouldCallFirst = true;
 }

 public int ShouldCallTwice(string s) {
  if (!ShouldCallFirst)
   throw new AssertionException("ShouldCallTwice called before ShouldCallFirst");
  if (ShouldCallAtEnd)
   throw new AssertionException("ShouldCallTwice called after ShouldCallAtEnd");
  if (ShouldCallTwice >= 2)
   throw new AssertionException("ShouldCallTwice called more than twice");
  ShouldCallTwice++;
  return StringToInteger(s);
 }

 public void ShouldCallAtEnd() {
  if (!ShouldCallFirst)
   throw new AssertionException("ShouldCallAtEnd called before ShouldCallFirst");
  if (ShouldCallTwice != 2) throw new AssertionException("ShouldCallTwice not called twice");
  ShouldCallAtEnd = true;
 }

}
Alireza Rahmani Khalili
źródło
1

fake objectjest prawdziwą implementacją interfejsu (protokołu) lub rozszerzenia z wykorzystaniem dziedziczenia lub innych podejść, których można użyć do stworzenia - jest zależność. Zwykle jest on tworzony przez programistę jako najprostsze rozwiązanie zastępujące pewną zależność

stub objectjest nagim obiektem (0, zero i metody bez logiki) ze stanem dodatkowym i predefiniowanym (przez programistę) do definiowania zwracanych wartości. Zwykle jest tworzony przez framework

mock objectjest bardzo podobny do stanustub object dodatkowego jest zmieniany podczas wykonywania programu, aby sprawdzić, czy coś się stało (wywołano metodę).

yoAlex5
źródło