Ложное поведение ActiveRecord в тестах RSpec - PullRequest
11 голосов
/ 29 января 2010

Я столкнулся с этой проблемой при тестировании. Предположим, у меня есть две модели, Пользователь и Пост, где пользователь has_many: posts.

Я пытаюсь определить блок кода, который включает в себя что-то вроде этого:

user = User.find(123)
post = user.posts.find(456)

Я знаю, как высмеивать части User.find и user.posts. Макет user.posts возвращает массив объектов Post. И когда дело доходит до .find(456) части, все ломается с исключением no block given.

Итак, мой вопрос здесь: что я возвращаю в результате макета user.posts, чтобы метод .find(456) работал на нем? User.first.posts.class говорит, что это Array, но, очевидно, есть еще кое-что, что делает вызовы в стиле AR работать. Я не в восторге от возможности найти метод поиска на возвращаемом объекте.

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

Ответы [ 2 ]

16 голосов
/ 29 января 2010

Проблема в том, что user.posts не на самом деле простой Array; это объект прокси ассоциации. Способ заглушки это, вероятно, что-то вроде этого (хотя точный синтаксис зависит от того, какую среду моделирования вы используете):

def setup
  @user = mock(User)
  User.stub(:find).with(123).return(@user)
  user_posts = mock(Object)
  @user.stub(:posts).return(user_posts)
  @post = mock(Post)
  user_posts.stub(:find).with(456).return(@post)
end

Тогда в вашем тесте User.find(123) вернет @user, а @user.posts.find(456) вернет @post. Если вам нужно, чтобы @user.posts действовал как Array в ваших тестах, вы можете создать mock(Array) и заглушить метод [](index).

7 голосов
/ 04 июня 2010

Вы можете посмотреть на метод stub_chain, предлагаемый RSpec.

http://apidock.com/rspec/Spec/Mocks/Methods/stub_chain#855-stub-chain-is-very-useful-when-testing-controller-code

Обновление: Per ryan2johnson9 обновленная документация: https://relishapp.com/rspec/rspec-mocks/v/3-2/docs/working-with-legacy-code/message-chains

...