TL;DR I'd like to know if I can test model methods that use querying (i.e find
, where
) without persisting test objects to the database.
So I'm new to rails, and working on an existing codebase.
One thing I've noticed is that our unit tests take forever to run.
Upon investigation, the culprit was, of course, that we persist everything to DB when we test our models.
So, I set out to try and write model tests that don't hit the DB, but I've come across a snag:
When a model has an association with other models, any operations that are performed on it assume that everything is persisted.
Let's take a look at an example-
class Parent < ActiveRecord::Base
has_many :children, dependent: :destroy
def default_child
children.find_by(default: true)
end
end
So naturally I want to test that my default_child
method is working:
parent = Parent.new
default_child = parent.children.build(default: true)
assert_equal default_child, parent.default_child
but this test fails, because the actual result of parent.default_child
is nil
!
This is because internally, the default_child
method uses find_by
, which, it seems, only works in the context of persisted objects.
So I'm forced to write the test like 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
Which is uglier and slower.
Is there any way I can test these operations in memory?
I've tried setting children
manually (parent.children = [ child1, child2 ]
).
This does not cause an error, but it seems that find_by
doesn't look there, but rather in the DB...
I see that a similar question came up 3 years ago, without a conclusive answer, I'm wondering if anything's changed since then..
P.S. bonus question- what can I do about validations which are on: update
? seems like I have to persist the test object at least once before they are invoked..
Aucun commentaire:
Enregistrer un commentaire