Стабильные методы с Rspec
Я хочу вызвать named_scope, который будет возвращать только одну запись, но named_scope возвращает массив, что не очень важно, поскольку я могу просто связать его с .first:
Model.named_scope(param).first
и это работает, с чем я борюсь, - как заглушить цепочку. Кто-нибудь имеет ссылку или ответ о том, как я буду добиваться этого с помощью Rspec насмехаясь?
Ответы
Ответ 1
Я что-то понял.
Client.stub!(:named_scope).and_return(@clients = mock([Client]))
@clients.stub!(:first).and_return(@client = mock(Client))
который позволяет мне вызвать мой контроллер:
@client = Client.named_scope(param).first
Это работает, но есть ли лучшее решение?
EDIT:
Выпуск rspec 1.2.6 позволяет нам использовать значение stub_chain, которое теперь может быть:
Client.stub_chain(:named_scope, :chained_call).and_return(@clients = [mock(Client)])
Это была моя голова, как всегда проверяйте api на специфику:)
Ответ 2
Лучшая версия
Client.stub!(:named_scope).and_return(@clients = mock([Client]))
@clients.stub!(:first).and_return(@client = mock(Client))
будет:
Client.should_receive(:named_scope).with(param).and_return do
record = mock_model(Comm)
record.should_receive(:do_something_else)
[record]
end
Ответ 3
Вопрос довольно старый, и, следовательно, есть несколько улучшений в том, как можно сделать это. Теперь вы можете использовать метод stub_chain для блокировки цепочки вызовов методов.
Например:
@client = Client.named_scope(param).first
можно обрезать с помощью
Client.stub_chain(:named_scope,:first).and_return(@client = mock(Client))
Дополнительные примеры stub_chaining:
describe "stubbing a chain of methods" do
subject { Object.new }
context "given symbols representing methods" do
it "returns the correct value" do
subject.stub_chain(:one, :two, :three).and_return(:four)
subject.one.two.three.should eq(:four)
end
end
context "given a string of methods separated by dots" do
it "returns the correct value" do
subject.stub_chain("one.two.three").and_return(:four)
subject.one.two.three.should eq(:four)
end
end
end
или просмотрите:
Да здравствует rspecs!!!:)
Ответ 4
Я полагаю, что это в спецификации контроллера?
Ваше собственное предложение должно работать нормально. Другая возможность - переместить вызов named_scope внутри вашей модели, чтобы избежать проблемы полностью. Это также будет соответствовать советам "толстые модели, тонкие контроллеры".
Ответ 5
Я думаю, что вы уже сделали тонкую задачу контроллера, поставив запрос в именованную область, где ее можно использовать повторно. Вот какой код я использовал до того, как начал использовать именованные области.
def mock_comm(stubs={})
@mock_comm ||= mock_model(Comm, stubs)
end
describe "responding to GET index" do
it "should expose all comms as @comms" do
Comm.should_receive(:find).with(:all).and_return([mock_comm])
get :index
assigns[:comms].should == [mock_comm]
end
# ...
Я бы, вероятно, написал код, очень похожий на то, что у вас уже есть, но, возможно, поставьте его в помощнике, который позволяет мне его повторно использовать. Другое дело - использовать другую насмешливую структуру, которая может дать вам больше контроля. Взгляните на railscast Райана Бейтса на RSpec - это немного устарело, но все же есть хорошие идеи.