2008-08-28 32 views

Trả lời

35

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 đó.

+0

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

+0

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 ... –

15

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 
+0

Chúng tôi đã làm theo phương pháp này và nó hoạt động tuyệt vời –

4

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

+0

Kể từ Rails 3.1 có một phương pháp vô hiệu hóa cho các nhà quan sát. –

+0

+1 no_peeping_toms –

2

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 
Các vấn đề liên quan