Giả sử bạn có ActiveRecord :: Observer trong một trong các ứng dụng Ruby on Rails của bạn - làm thế nào để bạn kiểm tra người quan sát này với rSpec?Làm thế nào để bạn kiểm tra các nhà quan sát với rSpec trong ứng dụng Ruby on Rails?
Trả lời
Bạn đang ở bên phải theo dõi, nhưng tôi đã gặp phải một số lỗi tin nhắn không mong muốn khi sử dụng rSpec, người quan sát và đối tượng giả. Khi tôi đang thử nghiệm mô hình của mình, tôi không muốn phải xử lý hành vi của người quan sát trong các kỳ vọng về thông điệp của mình.
Trong ví dụ của bạn, không có cách nào thực sự tốt để mô tả "set_status" trên mô hình mà không biết người quan sát sẽ làm gì với nó.
Vì vậy, tôi muốn sử dụng "No Peeping Toms" plugin. Với mã của bạn ở trên và sử dụng các plugin Không Peeping Toms, tôi sẽ spec mô hình như thế này:
describe Person do
it "should set status correctly" do
@p = Person.new(:status => "foo")
@p.set_status("bar")
@p.save
@p.status.should eql("bar")
end
end
Bạn có thể spec mã mô hình của bạn mà không cần phải lo lắng rằng có một người quan sát ở đó sẽ đi vào và che đậy giá trị của bạn. Bạn muốn spec mà riêng trong person_observer_spec như thế này:
describe PersonObserver do
it "should clobber the status field" do
@p = mock_model(Person, :status => "foo")
@obs = PersonObserver.instance
@p.should_receive(:set_status).with("aha!")
@obs.after_save
end
end
Nếu bạn REALLY REALLY muốn kiểm tra Model cùng và lớp Observer, bạn có thể làm điều đó như thế này:
describe Person do
it "should register a status change with the person observer turned on" do
Person.with_observers(:person_observer) do
lambda { @p = Person.new; @p.save }.should change(@p, :status).to("aha!)
end
end
end
99% số thời gian, tôi muốn kiểm tra spec với các nhà quan sát tắt. Nó dễ dàng hơn theo cách đó.
Disclaimer: Tôi chưa bao giờ thực sự làm điều này trên một trang web sản xuất, nhưng có vẻ như một cách hợp lý sẽ được sử dụng các đối tượng giả, should_receive
và bạn bè, và gọi các phương pháp trên quan sát trực tiếp
Do sau mô hình và quan sát:
class Person < ActiveRecord::Base
def set_status(new_status)
# do whatever
end
end
class PersonObserver < ActiveRecord::Observer
def after_save(person)
person.set_status("aha!")
end
end
tôi sẽ viết một spec như thế này (tôi chạy nó, và nó đi)
describe PersonObserver do
before :each do
@person = stub_model(Person)
@observer = PersonObserver.instance
end
it "should invoke after_save on the observed object" do
@person.should_receive(:set_status).with("aha!")
@observer.after_save(@person)
end
end
Chúng tôi đã làm theo phương pháp này và nó hoạt động tuyệt vời –
no_peeping_toms bây giờ là một viên ngọc và có thể được tìm thấy ở đây: https://github.com/patmaddox/no-peeping-toms
Kể từ Rails 3.1 có một phương pháp vô hiệu hóa cho các nhà quan sát. –
+1 no_peeping_toms –
Nếu bạn muốn kiểm tra rằng người quan sát quan sát mô hình chính xác và nhận được thông báo như mong đợi, đây là một ví dụ sử dụng RR.
your_model.rb:
class YourModel < ActiveRecord::Base
...
end
your_model_observer.rb:
class YourModelObserver < ActiveRecord::Observer
def after_create
...
end
def custom_notification
...
end
end
your_model_observer_spec.rb:
before do
@observer = YourModelObserver.instance
@model = YourModel.new
end
it "acts on the after_create notification"
mock(@observer).after_create(@model)
@model.save!
end
it "acts on the custom notification"
mock(@observer).custom_notification(@model)
@model.send(:notify, :custom_notification)
end
Nếu bạn muốn kiểm tra các nhà quan sát sau đó một mẫu tôi sử dụng là 'mô tả PersonOb server { xung quanh (: mỗi) {| spec | Person.with_observers (: person_observer) {spec.run}}} 'Điều này cho phép người quan sát cho tất cả các thử nghiệm trong PersonObserver mô tả khối. – roo
Câu trả lời này được phát âm như một câu trả lời, nhưng không rõ ràng về những gì. Nó chắc chắn không trả lời trực tiếp cho câu hỏi ... –