RSpec: bagaimana cara menguji apakah suatu metode dipanggil?

112

Saat menulis tes RSpec, saya mendapati diri saya menulis banyak kode yang terlihat seperti ini untuk memastikan bahwa sebuah metode dipanggil selama pelaksanaan tes (demi argumen, anggap saja saya tidak bisa benar-benar menginterogasi status objek setelah panggilan karena operasi yang dilakukan metode tidak mudah untuk melihat efeknya).

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

Yang ingin saya ketahui adalah: Apakah ada sintaks yang lebih bagus yang tersedia dari ini? Apakah saya kehilangan beberapa RSpec funky yang akan mengurangi kode di atas menjadi beberapa baris? should_receiveterdengar seperti itu harus melakukan ini tetapi membaca lebih lanjut kedengarannya seperti itu tidak persis seperti itu.

Mikey Hogarth
sumber
3
Periksa di sini: stackoverflow.com/questions/1328277/…
kddeisz
@ Peter Alfvin OP meminta sintaks should_receive, jadi saya pikir pertanyaan itu akan membantu.
kddeisz

Jawaban:

141
it "should call 'bar' with appropriate arguments" do
  expect(subject).to receive(:bar).with("an argument I want")
  subject.foo
end
orang gila
sumber
1
Maaf, saya tidak mengerti bagaimana format "to .. accept (: bar)" memeriksa nilai "calling_bar" dalam contoh ini. Bisakah Anda menjelaskan itu kepada saya?
ecoding5
2
@ ecoding5 no. Itu tidak dan tidak harus diperiksa called_bar. Itu hanya sebuah tanda untuk memastikan bahwa metode tersebut dipanggil, tetapi expect(...).to receive(...)Anda sudah menutupinya. Ini lebih jelas dan semantik
aneh
@wacko oooh, mengerti, terima kasih sudah menyelesaikannya. Saya tidak menangkapnya pertama kali.
ecoding5
102

Dalam rspec expectsintaks baru ini akan menjadi:

expect(subject).to receive(:bar).with("an argument I want")
Uri Agassi
sumber
37

Di bawah ini harus bekerja

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

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

bjhaid.dll
sumber
Terima kasih - Saya menerima "NoMethodError" has_received? - pikir ini mungkin ada hubungannya dengan versoins rspec sekalipun. Saya menemukan solusi lain yang berhasil untuk saya (yang ditandai benar di atas)
Mikey Hogarth
@MikeyHogarth Jawaban ini menyarankan have_received(setelah fakta pendekatan "mata-mata"), bukan has_received, yang bukan bagian dari versi RSpec mana pun yang saya tahu.
Peter Alfvin
2

Untuk sepenuhnya mematuhi sintaks RSpec ~> 3.1 dan rubocop-rspecopsi default untuk aturan RSpec/MessageSpies, inilah yang dapat Anda lakukan dengan spy:

Ekspektasi pesan meletakkan ekspektasi contoh di awal, sebelum Anda menjalankan code-under-test. Banyak pengembang lebih suka menggunakan pola tata-tindakan-pernyataan (atau diberikan-saat-kemudian) untuk menyusun pengujian. Mata-mata adalah jenis tes ganda alternatif yang mendukung pola ini dengan memungkinkan Anda mengharapkan bahwa pesan telah diterima setelah fakta, menggunakan has_received.

# arrange.
invitation = spy('invitation')

# act.
invitation.deliver("[email protected]")

# assert.
expect(invitation).to have_received(:deliver).with("[email protected]")

Jika Anda tidak menggunakan rubocop-rspec atau menggunakan opsi non-default. Anda tentu saja dapat menggunakan RSpec 3 default dengan harapan.

dbl = double("Some Collaborator")
expect(dbl).to receive(:foo).with("[email protected]")
Yi Zeng
sumber