2016-03-13 2 views
1

Я пытаюсь написать спецификации, которые тестируют некоторый класс, вызывает метод на кучке объектов activerecord (найденных по области).mocking Результаты ActiveRecord без stubbing в rspec

Это не работает:

#someworker_spec.rb 
10.times.map { create(:foo) }.each { |f| expect(f).to receive(:bar) 
SomeWorker.perform 

#someworker.rb 
class SomeWorker 
    Foo.some_scope.each(&:bar) 
end 

Поскольку ActiveRecord возвращает новые экземпляры объектов, поэтому экземпляр объекта, возвращаемый ActiveRecord никогда не получить этот метод.

Я знаю, что могу просто заглушить метод some_scope и вернуться с удвоением ожиданий, но это кажется хрупким. Я бы предпочел проверить, что соответствующие объекты foo получают этот метод. Есть ли способ сделать то, что я пытаюсь сделать над работой?

ответ

2

Вы могли бы сделать это с and_wrap_original

expect(Foo).to receive(:some_scope).and_wrap_original {|relation| 
    relation.call.each {|record| expect(record).to receive(:bar)} 
} 

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

+0

Фредерик - единственная проблема с этим в том, что он действительно не проверяет, что предполагаемые модели activerecord получают метод, так как мой (не работает) код делает в вопросе. это единственный способ достичь этого здесь, чтобы добавить дополнительную строку внутри блока 'and_wrap_original', которая имеет другое ожидание:' ожидать (отношение.call.map (&: id)). to match_array (factory_created_objects.map (&: id)) '? – jtmarmon

+1

Уверен, что вы могли бы это сделать, но лично я просто специфицировал область действия отдельно. –