0

TL; DR Я хотел бы знать, если я могу проверить методы модели, которые используют запрашивая (т.е. find, where) без сохраняющиеся объектов испытаний в базе данных.рельсы Модульное тестирование с ActiveRecord ассоциаций без удара DB

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

Давайте посмотрим на ПРИМЕР-

class Parent < ActiveRecord::Base 
    has_many :children, dependent: :destroy 

    def default_child 
    children.find_by(default: true) 
    end 

end 

Поэтому, естественно, я хочу, чтобы проверить, что мой default_child метод работает:

parent = Parent.new 
default_child = parent.children.build(default: true) 

assert_equal default_child, parent.default_child 

, но этот тест не удается, так как фактический результат parent.default_child есть nil!
Это связано с тем, что внутри метода default_child используется find_by, который, кажется, работает только в контексте сохраняемых объектов.

Так что я вынужден написать тест, как SO-

parent = Parent.new 
# I don't want to do this!! 
parent.save 
# why 'create' and not 'build'? 
default_child = parent.children.create(default: true) 

assert_equal default_child, parent.default_child 

Что уродливее и медленнее.
Есть ли способ проверить эти операции в памяти?

Я пробовал установить children вручную (parent.children = [ child1, child2 ]).
Это не вызывает ошибку, но мне кажется, что find_by не смотрит туда, а в БД ...

я вижу, что a similar question пришел 3-х лет назад, без окончательного ответа, я интересно, изменилось ли что-то с тех пор.

PS бонусный вопрос - что я могу сделать для валидаций, которые являются on: update? похоже, что я должен упорствовать в тестовом объекте хотя бы один раз, прежде чем они будут вызваны.

ответ

1

Последний вопрос. Для валидаций, просто утверждают, что модель valid?:

parent = Parent.new 
assert parent.valid? 

Что касается он главный вопрос, нет хорошего ответа на это, и люди имеют философские разногласия о том, как вещи, как они должны быть проверены. Мое мнение состоит в том, что вы должны тестировать свою бизнес-логику и избегать тестирования функциональных возможностей, предоставляемых вам инфраструктурой (по-видимому, уже проверены тестами, включенными в саму структуру).

Я думаю, что вы хотите, чтобы проверить бизнес-логику Parent#default_child (кстати, она не должна быть default_children?), Что только возвращает связанный Child объекты с default = true.Предполагая, что вы доверяете ActiveRecord для правильной работы, вы можете высмеять (вам нужно добавить Mocha или использовать что-то вроде RSpec) find_by(default: true), чтобы всегда возвращать объект Child с размером default, который должен быть установлен в true. Потому что вы доверяете, что ActiveRecord сделают это за вас. Но я бы не издевался над каждым методом ActiveReocrd. Вы потратите много времени и не будете очень счастливы в конце.

Для некоторых тестов вы можете обнаружить, что вам абсолютно необходимы данные. Вы можете использовать fixtures available in Rails или использовать что-то вроде FactoryGirl

+0

Да, это то, что я думал. Я мог бы пойти и посмотреть на насмешливый ActiveRecord, хотя я не очень в восторге от этой перспективы. Кстати, мой последний вопрос касался утверждений, которые являются 'on: update', поэтому ваш ответ не будет работать в этом случае (сначала нужно сохранить« родительский »). –