2010-11-11 12 views
45

Mam model z prywatną metodą, którą chciałbym dodać do RSpec,
jak zwykle robisz? Czy testujesz tylko metodę wywołującą połączenie prywatne?
lub określić również prywatny? jeśli tak, jak to zrobić?Jak określić metodę prywatną

Odpowiedz

109

Zawsze stosuję takie podejście: Chcę przetestować publiczny interfejs API, który udostępnia moja klasa.

Jeśli masz prywatne metody, dzwonisz do nich tylko z publicznych metod, które wystawiasz innym klasom. Jeśli więc przetestujesz, że te publiczne metody działają zgodnie z oczekiwaniami w każdych warunkach, udowodniłeś również, że prywatne metody, z których korzystają, działają również.

Przyznam, że natrafiłem na szczególnie skomplikowane metody prywatne. W skrajnym przypadku, gdy chcesz je przetestować, można to zrobić:

@obj.send(:private_method) 
+1

Dziękuję za pomoc, zgadzam się, że testowanie publicznej metody dowodzi, że prywatny również działa. Mówiąc o tym, naprawdę chcę przetestować prywatną metodę, a twoje rozwiązanie działa jak czar, dzięki! – Mike

+2

Oto kolejna interesująca metoda: http://kailuowang.blogspot.com/2010/08/testing-private-methods-in-rspec.html – gucki

+1

Mam hook before_save w moim modelu, który zapisuje prywatny token do bazy danych poprzez prywatny Metoda "make_private_token". Metoda 'make_private_token' używa publicznych metod klasy, a nie odwrotnie, więc jedyny sposób, w jaki mogę to przetestować, to metoda 'send'. Nie widzę w tym nic 'ekstremalnego' ... – Starkers

6

dla metod prywatnych, które wymagają pokrycia kodu (tymczasowo lub na stałe), użyj rspec-context-private gem tymczasowo uczynić metody prywatne publicznego w kontekście.

gem 'rspec-context-private' 

Działa poprzez dodanie współdzielonego kontekstu do projektu.

RSpec.shared_context 'private', private: true do 

    before :all do 
    described_class.class_eval do 
     @original_private_instance_methods = private_instance_methods 
     public *@original_private_instance_methods 
    end 
    end 

    after :all do 
    described_class.class_eval do 
     private *@original_private_instance_methods 
    end 
    end 

end 

Następnie, jeśli przejdą :private jako metadane do describe bloku, metody prywatne będą publiczne w tym kontekście.

class Example 
    private def foo 
    'bar' 
    end 
end 

describe Example, :private do 
    it 'can test private methods' do 
    expect(subject.foo).not eq 'bar' 
    end 
end 
+0

Nie wiem, czy już dłużej utrzymujesz ten klejnot, ale twoja dokumentacja nie ma bloku kodu dotyczącego deklarowania shared_context. Więc nie mogłem go uruchomić po prostu czytając dokumentację. Po dodaniu do tego bloku działa zgodnie z oczekiwaniami. – istrasci

0

Jeśli chcąc przetestować oczekiwanie na prywatnej metody, zaakceptowane odpowiedź nie będzie naprawdę działa (przynajmniej nie o tym nie wiem, więc jestem otwarty na korekty w tej kwestii). Co zrobiłem zamiast nawet filthier - w samym teście tylko narazić metodę poprzez przekształcenie go:

def object_to_test.my_private_method 
    super 
end 

Works na Ruby 1.8, nie mogę wypowiedzieć się na dowolny z nowszych czasach pracy.

Powiązane problemy