Testowanie błędów połączenia

Chciałbym w swoich testach klienta HTTP symulować błędy połączenia z serwerem i testować obsługę tych błędów, np. “klient powinnien spróbować zapytać ponownie do max. 3 razy jeśli otrzymał Exception, connection reset by peer” itd.

Zastanawiałem się w jaki sposób to ugryźć i nic sensownego mi nie przychodzi do głowy.
Np. powiedzmy, że korzystając z rspec’a mogę napisać (testujemy HttpClient.get):

it "should retry max 3 times etc...." do Net::HTTP.should_receive(:start).and_raise(Exception) HttpClient.get(request('/problematic')) end
Takie rozwiązanie nie jest dobre bo chciałbym oprócz zasymulowania że np. któraś z metod Net::HTTP rzuca wyjątkiem za 3 razem wywołać jednak właściwą metodę, która zwróci poprawny “response”. Poza tym dobrze byłoby móc kontrolować co dzieje się po wywołaniu każdego requestu (rzucany jest wyjątek czy nie).

Idealnie byłby mieć do dyspozycji “zepsuty” serwer HTTP, ew. próbować testować nieistniejące host’y ale testy będą się wykonywać bardzo długo (domyślny 60 sekundowy timeout w Net::HTTP, który można zmniejszyć ale nie jest to idealne bo zawsze pozostanie jakaś pauza przy wykonywaniu testów).

Z obsługą rzeczy typu statusy 404, 301, 500 poradziłem sobie pisząc specjalne handlery do Mongrela które zwracają potrzebne nagłówki, body etc. ale nie wiem jak ugryźć problemy z połączeniem na poziomie sieci.

Jakieś pomysły ?

Możesz przecież zasymulować zwracanie poprawnej odpowiedzi tak samo jak zwracanie wyjątku.

Net::HTTP.stub!(:start).and_return("poprawna odpowiedź")

Problem w tym, że po zrobieniu:

it "should retry max 3 times etc...." do Net::HTTP.should_receive(:start).and_raise(Exception) HttpClient.get(request('/problematic')) end
tracę odniesienie do prawdziwej metody start, istnieje tylko stubbowana wersja, ja chcę zasymulować np 3 requesty w jednym teście:

  1. Exception
  2. Exception
  3. Response OK

Spróbuję z alias_method_chain na którejś z metod Net.