Подтвердить что ты не робот

Стабильные методы с Rspec

Я хочу вызвать named_scope, который будет возвращать только одну запись, но named_scope возвращает массив, что не очень важно, поскольку я могу просто связать его с .first:

Model.named_scope(param).first

и это работает, с чем я борюсь, - как заглушить цепочку. Кто-нибудь имеет ссылку или ответ о том, как я буду добиваться этого с помощью Rspec насмехаясь?

4b9b3361

Ответ 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 - это немного устарело, но все же есть хорошие идеи.