Сцепление цепочечных запросов в Rails 3 и Rspec - PullRequest
14 голосов
/ 30 октября 2010

Я пытаюсь проверить имеющуюся область, основанную на цепочке других областей. («public_stream» ниже).

scope :public, where("entries.privacy = 'public'")
scope :completed, where("entries.observation <> '' AND entries.application <> ''")
scope :without_user, lambda { |user| where("entries.user_id <> ?", user.id) }
scope :public_stream, lambda { |user| public.completed.without_user(user).limit(15) }

Используя такой тест:

    it "should use the public, without_user, completed, and limit scopes" do
      @chain = mock(ActiveRecord::Relation)
      Entry.should_receive(:public).and_return(@chain)
      @chain.should_receive(:without_user).with(@user).and_return(@chain)
      @chain.should_receive(:completed).and_return(@chain)
      @chain.should_receive(:limit).with(15).and_return(Factory(:entry))

      Entry.public_stream(@user)
    end

Тем не менее, я продолжаю получать эту ошибку:

Failure/Error: Entry.public_stream(@user)
undefined method `includes_values' for #<Entry:0xd7b7c0>

Кажется, include_values ​​является переменной экземпляра объекта ActiveRecord :: Relation, но когда я пытаюсь заглушить его, я все равно получаю ту же ошибку Мне было интересно, есть ли у кого-нибудь опыт работы с новыми цепочечными запросами в Rails 3? Я могу найти кучу обсуждений по поводу хеша 2.x find, но ничего о том, как проверить, что сейчас.

Ответы [ 4 ]

21 голосов
/ 19 января 2011

Я использую для этого rspec's stub_chain.Вы можете использовать что-то вроде:

some_model.rb

scope :uninteresting, :conditions => ["category = 'bad'"],
                      :order => "created_at DESC"

Контроллер

@some_models = SomeModel.uninteresting.where(:something_else => true)

spec

SomeModel.stub_chain(:uninteresting, :where) {mock_some_model}
3 голосов
/ 16 апреля 2014

Тот же ответ, что и выше.

SomeModel.stub_chain(:uninteresting, :where) {mock_some_model}

Версия Rspec 3:

allow(SomeModel).to receive_message_chain(:uninteresting).and_return(SomeModel.where(nil))

Ссылка:

https://relishapp.com/rspec/rspec-mocks/docs/method-stubs/stub-a-chain-of-methods

1 голос
/ 09 апреля 2012

Прежде всего, вы, вероятно, не должны тестировать встроенную функциональность Rails.

Вы должны писать модульные тесты только для кода, который вы написали самостоятельно (что должно быть второстепенным, если вы практикуете TDD) - Rails поставляется со своим собственным комплексным набором модульных тестов для егофункциональность - нет смысла реплицировать это.

Что касается выдаваемой ошибки, я думаю, что ваша проблема в этой строке:

@chain.should_receive(:limit).with(15).and_return(Factory(:entry))

Вы ожидаетецепочка для возврата Factory, которая фактически была бы экземпляром ActiveRecord, но в действительности каждое отношение возвращает еще одну ActiveRecord::Relation.

Таким образом, само ваше ожидание неверно и, возможно, действительно вызывает ошибку, которая выдается.

Имейте в виду, что области действия на самом деле не возвращают ожидаемые вами записи, пока вы явно не укажетеперебирать их.Кроме того, записи отношения не будут никогда возвращать одну запись.Они будут всегда либо возвращать пустой массив или массив с записями.

0 голосов
/ 03 января 2011

Попробуйте передать Ареля, так как это может привести к тому, что его границы пропадают.

it "should use the public, without_user, completed, and limit scopes" do
  @chain = Entry
  @chain.should_receive(:public).and_return(@chain.public)
  @chain.should_receive(:without_user).with(@user).and_return(@chain.without_user(@user))
  @chain.should_receive(:completed).and_return(@chain.completed)
  @chain.should_receive(:limit).with(15).and_return(Factory(:entry))

  Entry.public_stream(@user)
end
...