2013-04-06 16 views
16

Rozszerzam istniejącą bibliotekę, tworząc klasę potomną, która rozciąga się do klasy biblioteki.Jak mogę kpić super w rubinach za pomocą rspec?

W klasie podrzędnej mogłem przetestować większość funkcji w metodzie initialize, ale nie mogłem wyśmiać połączenia super. Klasa dziecka wygląda jak coś poniżej.

class Child < SomeLibrary 
    def initialize(arg) 
     validate_arg(arg) 
     do_something 
     super(arg) 
    end 

    def validate_arg(arg) 
     # do the validation 
    end 

    def do_something 
     @setup = true 
    end 
end 

Jak mogę napisać rspec testu (z mocha) taką, że mogę Mock super połączenie? Zauważ, że testuję funkcjonalność metody initialize w klasie Child. Czy muszę utworzyć oddzielną ścieżkę kodu, która nie wywołuje super, gdy jest dostarczana z dodatkowym argumentem?

Odpowiedz

15

Nie możesz kpić z super, a nie powinieneś. Kiedy wyśmiewasz coś, sprawdzasz, czy otrzymałeś określoną wiadomość, a super nie jest wiadomością - to słowo kluczowe.

Zamiast tego sprawdź, jakie zachowanie tej klasy zmieni się, jeśli brakuje połączenia super, i napisz przykład, który sprawdzi i weryfikuje to zachowanie.

+1

Czy to znaczy, że nie może pisać RSpec test zainicjować? Czy pisanie testów jednostkowych dla metody inicjalizacji jest złą praktyką? Nawiasem mówiąc, rozbudowuję bibliotekę konektorów baz danych. Jeśli nie piszę testu jednostkowego, ale piszę test integracji, po prostu myślę, że to dziwne, jeśli test rspec wymaga połączenia z prawdziwą bazą danych. –

+0

Nie ma dla mnie sensu, dlaczego nie możemy kpić super. Wydaje się to przydatne, aby odpowiednio przetestować zachowanie inicjacyjne w izolacji, a na pewno super jest wiadomością wysłaną do instancji klasy, nie? –

+1

Nie, 'super' to _nie_ wiadomość wysłana do instancji klasy. Nie mam żadnych rubinowych metaprogramujących konstrukcji, które by to umożliwiały, a nawet gdyby tak było, nadal nie jestem przekonany, że to dobry pomysł. –

1

Dobrym sposobem na sprawdzenie tego jest, aby ustawić oczekiwanie jakiegoś działania podjęte przez nadklasy - przykład:

class Some::Thing < Some 
def instance_method 
    super 
end 
end 

i super klasy:

class Some 
    def instance_method 
    another_method 
    end 

    def self.another_method # not private! 
    'does a thing' 
    end 
end 

teraz Test:

describe '#instance_method' do 
    it 'appropriately triggers the super class method' do 
     sawm = Some::Thing.new 
     expect(sawm).to receive(:another_method) 
     sawm.instance_method 
    end 
end 

Wszystko to określa, że ​​super został powołany w klasie nadrzędnej

Użyteczność tego wzoru zależy od tego, w jaki sposób konstruujesz swoje testy/jakie masz oczekiwania dotyczące mutacji dziecko/klasa pochodna, stosując metodę super.

także - zwracać szczególną uwagę na class i instance metod, trzeba będzie dostosować allows i expects Odpowiednio

YMMV

Powiązane problemy