Вы на правильном пути, но я столкнулся с рядом неприятных неожиданных сообщений об ошибках при использовании rSpec, наблюдателей и фиктивных объектов. Когда я тестирую свою модель на спецификациях, я не хочу обрабатывать поведение наблюдателя в моих ожиданиях.
В вашем примере нет действительно хорошего способа спецификации "set_status" для модели без знания того, что с ней собирается делать наблюдатель.
Поэтому я хотел бы использовать плагин "No Peeping Toms". Учитывая приведенный выше код и плагин 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
Вы можете указать свой код модели, не беспокоясь о том, что там будет наблюдатель, который придет и сожжет вашу ценность. Вы можете указать это отдельно в 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
Если вы ДЕЙСТВИТЕЛЬНО ДЕЙСТВИТЕЛЬНО хотите проверить связанный класс 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% времени, я бы предпочел спек-тест с отключенными наблюдателями. Так проще.