RSpec: Làm thế nào để kiểm tra xem một phương thức có được gọi không?


112

Khi viết các bài kiểm tra RSpec, tôi thấy mình đã viết rất nhiều mã trông giống như thế này để đảm bảo rằng một phương thức được gọi trong quá trình thực hiện kiểm tra (để tranh luận, hãy nói rằng tôi không thể thực sự thẩm vấn trạng thái của đối tượng sau lời gọi bởi vì thao tác mà phương thức thực hiện không dễ dàng để thấy tác dụng của).

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

Điều tôi muốn biết là: Có cú pháp nào đẹp hơn cái này không? Tôi có thiếu một số tính năng tuyệt vời RSpec vui nhộn có thể làm giảm đoạn mã trên xuống một vài dòng không? should_receivenghe có vẻ như nó nên làm điều này nhưng đọc thêm nó có vẻ như đó không phải là chính xác những gì nó làm.



@Peter Alfvin OP đang yêu cầu bật cú pháp should_receive, vì vậy tôi nghĩ câu hỏi đó sẽ hữu ích.
kddeisz

Câu trả lời:


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

1
Xin lỗi, tôi không hiểu cách định dạng "to .. accept (: bar)" kiểm tra giá trị của "call_bar" trong ví dụ này. Bạn có thể giải thích điều đó với tôi không?
ecoding5

2
@ ecoding5 không. Nó không và cũng không nên kiểm tra called_bar. Đó chỉ là một lá cờ để đảm bảo rằng phương thức đã được gọi, nhưng với expect(...).to receive(...)bạn, bạn đã bao gồm điều đó. Nó rõ ràng và có ngữ nghĩa hơn
wacko

@wacko oooh, hiểu rồi, cảm ơn vì đã xóa. Tôi đã không nắm bắt được nó lần đầu tiên.
ecoding5


37

Dưới đây sẽ hoạt động

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

Tài liệu: https://github.com/rspec/rspec-mocks#expecting-arguments


Cảm ơn bạn - Tôi đã nhận được "NoMethodError" has_receive? - mặc dù nghĩ rằng điều này có thể liên quan đến rspec so với các đối thủ. Tôi tìm thấy một giải pháp mà làm việc cho tôi (được đánh dấu đúng ở trên)
Mikey Hogarth

@MikeyHogarth Câu trả lời này là gợi ý have_received(sau khi thực tế là cách tiếp cận "gián điệp"), không phải has_received, không phải là một phần của bất kỳ phiên bản RSpec nào mà tôi biết.
Peter Alfvin

2

Để tuân thủ hoàn toàn cú pháp RSpec ~> 3.1 và rubocop-rspeclà tùy chọn mặc định của quy tắc RSpec/MessageSpies, đây là những gì bạn có thể làm với spy:

Kỳ vọng thông báo đặt kỳ vọng của ví dụ ngay từ đầu, trước khi bạn gọi kiểm tra mã dưới dạng. Nhiều nhà phát triển thích sử dụng mẫu sắp xếp-hành động-khẳng định (hoặc cho-khi-thì) để cấu trúc các bài kiểm tra. Gián điệp là một loại thử nghiệm kép thay thế hỗ trợ mô hình này bằng cách cho phép bạn mong đợi rằng một tin nhắn đã được nhận sau thực tế, bằng cách sử dụng has_renition.

# arrange.
invitation = spy('invitation')

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

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

Nếu bạn không sử dụng rubocop-rspec hoặc sử dụng tùy chọn không mặc định. Tất nhiên, bạn có thể sử dụng RSpec 3 mặc định với mong đợi.

dbl = double("Some Collaborator")
expect(dbl).to receive(:foo).with("foo@example.com")
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.