Вопрос

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

Model.named_scope(param).first

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

Это было полезно?

Решение

Я кое-что выяснил.

Client.stub!(:named_scope).and_return(@clients = mock([Client]))
@clients.stub!(:first).and_return(@client = mock(Client))

что позволяет мне вызвать мой контроллер:

@client = Client.named_scope(param).first

Это работает, но есть ли лучшее решение?

Редактировать:

Выпуск rspec 1.2.6 позволяет нам использовать stub_chain, что означает, что теперь это может быть:

Client.stub_chain(:named_scope, :chained_call).and_return(@clients = [mock(Client)])

Это было выше моих сил, как всегда, проверяйте API на предмет специфики :)

Другие советы

Лучшая версия

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

Вопрос довольно старый, и, следовательно, есть несколько улучшений в том, как можно выполнить заглушку.Теперь вы можете использовать метод 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!!!:)

Я полагаю, это есть в спецификации контроллера?

Ваше собственное предложение должно сработать нормально.Другая возможность заключается в перемещении вызова named_scope внутри вашей модели, чтобы полностью избежать проблемы.Это также соответствовало бы совету "толстые модели, тонкие контроллеры".

Я думаю, вы уже сделали с тонким контроллером, поместив запрос в именованную область, где его можно использовать повторно.Вот некоторый код, который я использовал до того, как начал использовать именованные области.

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top