RSpec: jak sprawdzić, czy metoda została wywołana?


112

Pisząc testy RSpec, piszę dużo kodu, który wygląda tak, aby upewnić się, że metoda została wywołana podczas wykonywania testu (ze względu na argument, powiedzmy, że tak naprawdę nie mogę przesłuchać stanu obiektu po wywołaniu, ponieważ operacja, którą wykonuje metoda, nie jest łatwa do zobaczenia).

describe "#foo"
  it "should call 'bar' with appropriate arguments" do
    called_bar = false
    subject.stub(:bar).with("an argument I want") { called_bar = true }
    subject.foo
    expect(called_bar).to be_true
  end
end

Chcę wiedzieć: czy jest dostępna ładniejsza składnia niż ta? Czy brakuje mi jakiejś fajnej niesamowitości RSpec, która zredukowałaby powyższy kod do kilku wierszy? should_receivewydaje się, że powinien to zrobić, ale czytając dalej, wydaje się, że to nie jest dokładnie to, co robi.



@Peter Alfvin OP prosił o włączenie składni should_receive, więc pomyślałem, że to pytanie pomoże.
kddeisz

Odpowiedzi:


141
it "should call 'bar' with appropriate arguments" do
  expect(subject).to receive(:bar).with("an argument I want")
  subject.foo
end

1
Przepraszamy, nie rozumiem, w jaki sposób ten format „to .. odbierać (: bar)” sprawdza wartość „named_bar” w tym przykładzie. Czy możesz mi to wyjaśnić?
ekodowanie 5

2
@ ecoding5 no. Tak nie jest i nie powinno się tego sprawdzać called_bar. To była tylko flaga zapewniająca, że ​​metoda została wywołana, ale z expect(...).to receive(...)tobą już to obejmuje. To jest bardziej przejrzyste i semantyczne
wacko

@wacko oooh, rozumiem, dzięki za wyjaśnienie tego. Nie złapałem tego za pierwszym razem.
ekodowanie 5


37

Poniższe powinno działać

describe "#foo"
  it "should call 'bar' with appropriate arguments" do
     subject.stub(:bar)
     subject.foo
     expect(subject).to have_received(:bar).with("Invalid number of arguments")
  end
end

Dokumentacja: https://github.com/rspec/rspec-mocks#expecting-arguments


Dziękuję - otrzymałem komunikat „NoMethodError” has_received? - myślę, że może to mieć związek z wersjami rspec. Znalazłem inne rozwiązanie, które zadziałało (to zaznaczone jako poprawne powyżej)
Mikey Hogarth

@MikeyHogarth Ta odpowiedź sugerowała have_received(po fakcie podejście „szpiegów”), a nie has_received, co nie jest częścią żadnej znanej mi wersji RSpec.
Peter Alfvin,

2

Aby w pełni zachować zgodność ze składnią RSpec ~> 3.1 i rubocop-rspecdomyślną opcją reguły RSpec/MessageSpies, oto co możesz zrobić z spy:

Oczekiwania dotyczące wiadomości umieszczają oczekiwanie przykładu na początku, zanim wywołasz testowany kod. Wielu programistów woli używać wzorca aranżuj-działaj-potwierdzaj (lub określ-kiedy-wtedy) do tworzenia struktury testów. Szpiedzy są alternatywnym typem podwójnych testów, które obsługują ten wzorzec, pozwalając ci oczekiwać, że wiadomość została odebrana po fakcie, używając funkcji have_received.

# arrange.
invitation = spy('invitation')

# act.
invitation.deliver("foo@example.com")

# assert.
expect(invitation).to have_received(:deliver).with("foo@example.com")

Jeśli nie używasz rubocop-rspec lub nie używasz opcji domyślnej. Możesz oczywiście użyć standardu RSpec 3 z oczekiwaniem.

dbl = double("Some Collaborator")
expect(dbl).to receive(:foo).with("foo@example.com")
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.