简体   繁体   English

您如何在Ruby on Rails应用程序中使用rSpec测试观察者?

[英]How would you test observers with rSpec in a Ruby on Rails application?

假设您的Ruby on Rails应用程序中有一个ActiveRecord :: Observer - 如何使用rSpec测试此观察者?

You are on the right track, but I have run into a number of frustrating unexpected message errors when using rSpec, observers, and mock objects. 您处于正确的轨道上,但在使用rSpec,观察者和模拟对象时,我遇到了许多令人沮丧的意外消息错误。 When I am spec testing my model, I don't want to have to handle observer behavior in my message expectations. 当我对我的模型进行规范测试时,我不希望在我的消息期望中处理观察者行为。

In your example, there isn't a really good way to spec "set_status" on the model without knowledge of what the observer is going to do to it. 在你的例子中,没有一种非常好的方法在模型上规定“set_status”而不知道观察者将对它做什么。

Therefore, I like to use the "No Peeping Toms" plugin. 因此,我喜欢使用“No Peeping Toms”插件。 Given your code above and using the No Peeping Toms plugin, I would spec the model like this: 鉴于上面的代码并使用No Peeping Toms插件,我会像这样指定模型:

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

You can spec your model code without having to worry that there is an observer out there that is going to come in and clobber your value. 你可以指定你的模型代码,而不必担心会有一个观察者会进来并破坏你的价值。 You'd spec that separately in the person_observer_spec like this: 您可以在person_observer_spec中单独指定,如下所示:

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 

If you REALLY REALLY want to test the coupled Model and Observer class, you can do it like this: 如果你真的想要测试耦合的Model和Observer类,你可以这样做:

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% of the time, I'd rather spec test with the observers turned off. 99%的时间,我宁愿在关闭观察员的情况下进行规范测试。 It's just easier that way. 这样更简单。

Disclaimer: I've never actually done this on a production site, but it looks like a reasonable way would be to use mock objects, should_receive and friends, and invoke methods on the observer directly 免责声明:我从来没有真正在生产网站上做过这个,但看起来合理的方式是使用模拟对象, should_receive和朋友,并直接在观察者上调用方法

Given the following model and observer: 鉴于以下模型和观察者:

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

I would write a spec like this (I ran it, and it passes) 我会写一个这样的规格(我跑了,它通过了)

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

no_peeping_toms现在是一个宝石,可以在这里找到: https//github.com/patmaddox/no-peeping-toms

If you want to test that the observer observes the correct model and receives the notification as expected, here is an example using RR. 如果要测试观察者是否观察到正确的模型并按预期接收通知,则以下是使用RR的示例。

your_model.rb: your_model.rb:

class YourModel < ActiveRecord::Base
    ...
end

your_model_observer.rb: your_model_observer.rb:

class YourModelObserver < ActiveRecord::Observer
    def after_create
        ...
    end

    def custom_notification
        ...
    end
end

your_model_observer_spec.rb: 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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM