Отказывание отношения поведения ActiveRecord в тестах RSpec
Я столкнулся с этой проблемой при тестировании. Предположим, у меня две модели: User и Post, где пользователь has_many: posts.
Я пытаюсь описать блок кода, который включает в себя что-то вроде этого:
user = User.find(123)
post = user.posts.find(456)
Я знаю, как издеваться над частями User.find
и user.posts
. user.posts
mock возвращает массив объектов Post. И когда он доходит до части .find(456)
, все ломается с исключением no block given
.
Итак, мой вопрос: что я возвращаю в результате user.posts
mock, так что метод .find(456)
работает на нем? User.first.posts.class
говорит, что это Array, но, очевидно, есть что-то большее, что заставляет работать называть AR-стиль. Меня не радует перспектива издеваться над методом find на возвращаемом объекте.
PS Прежде чем предлагать очевидный и хороший ответ о том, чтобы перестать насмехаться и использовать инвентарь/посев тестовой базы данных с необходимыми данными, вот схема уловки: устаревшая. Как пользователь, так и почта работают над представлениями базы данных без таблиц и меняют их так, чтобы они были таблицами в тестовой базе данных, мне кажется неправильным.
Ответы
Ответ 1
Проблема в том, что 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)
.
Ответ 2
Вы можете изучить метод stub_chain, предлагаемый RSpec.
http://apidock.com/rspec/Spec/Mocks/Methods/stub_chain#855-stub-chain-is-very-useful-when-testing-controller-code
Обновление: для ryan2johnson9 обновленная документация: https://relishapp.com/rspec/rspec-mocks/v/3-2/docs/working-with-legacy-code/message-chains