pitosalas
pitosalas

Reputation: 10852

Rails test data, in the database

This might be a basic misunderstanding on my part. I have a bunch of logic in my app which collects sets of data from several tables and combines them into memory structures. I want to write tests for that logic.

It seems to me that fixtures, factory girl and similar tools build in-memory model instances. If I do activerecord calls, like Model.find(foo: 12) won't those apply only against records that were saved?

Upvotes: 1

Views: 1769

Answers (3)

Siwei
Siwei

Reputation: 21559

In most cases, I agree with @mrbrdo's opinion: prefer rpsec's stub method. but as a rails programmer, I think you have to know both the "fixture" and the "stub".

Fixtures, whatever the yaml file or the factory girl data , will both save into database. see your config/database.yml file for the location where they are. Actually this is useful when you want to make sure that there is ALWAYS some data in the DB during your test, such as an "admin user" with a fixed ID.

Stubs, it's faster than fixture since it won't be saved into DB, and maybe very useful when you want to perform a test that can't implemented by "Fixtures".

So, I suggest that you try both of them in your real coding life, and choose either of them according to the real context.

Upvotes: 2

Fitzsimmons
Fitzsimmons

Reputation: 1581

FactoryGirl supports several build strategies, including one where records are saved to the database.

It's straightforward: FactoryGirl.create(:foo) will create a foo and save it to the database, whereas FactoryGirl.build(:foo) will only create the in-memory version of that object.

More information is available about build strategies here: https://github.com/thoughtbot/factory_girl/blob/master/GETTING_STARTED.md , in the "Using factories" section.

Upvotes: 1

mrbrdo
mrbrdo

Reputation: 8258

What you are saying is not true, fixtures or factory girl will use the database. I would avoid fixtures, though, people don't usually use them nowadays.

The proper way to really write your tests would be to stub out activerecord calls, though, because this will make your tests a lot faster. What you want to test is combining data into your structures, not pulling data out of the database - that part is already tested in activerecord's tests.

So stub out the finders like this (if you are using rspec):

Model.should_receive(:find).with(foo: 12) do
  Model.new(foo: 12, other_attribute: true)
end

So when the method you are testing calls Model.find(foo: 12) it will get

Model.new(foo: 12, other_attribute: true)

This is much faster than actually creating it in the database and then pulling it out, and there is no point in doing this for what you are testing - it's not important. You can also stub save on the instance and so on depending on what your method is doing. Keep in mind, retrieving data from DB and saving to DB is all already tested in activerecord's tests, there is no point for you to re-do these tests - just focus on your specific logic.

Upvotes: 1

Related Questions