2010-10-30 3 views
14

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

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> 

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

+1

Из любопытства, это работает, если вы не используете 'public'?Между вашим именем области и ключевым словом Ruby 'public' существует конфликт. Не уверен, что это проблема, но было бы интересно, где в цепочке этот тест терпит неудачу. –

+0

Области применения напрямую связаны с базой данных, поэтому нет смысла тестировать их изолированно. Просто создайте реальные записи и проверьте, что возвращает запрос. – RocketR

ответ

20

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

some_model.rb

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

контроллер

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

спецификации

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

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

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 
1

Во-первых, вы, вероятно, не должны испытывать Встроения в функции Rails.

You should only be writing unit tests for code that you have written yourself (which should be second-nature if you practice TDD) – Rails ships with its own comprehensive suite of unit tests for its built-functionality – there is no point in replicating this.

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

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

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

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

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

Смежные вопросы