Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Stubbing ActiveRecord associations

Say I have a Company which may contain many employees of type Employee may contain many tasks of type Task.

class Company < ActiveRecord::Base; has_many :employees; end
class Employee < ActiveRecord::Base; belongs_to :company, has_many :tasks; end
class Task < ActiveRecord::Base; belongs_to :employee; end

Using tools like FactoryGirl I may be tempted to create tasks using FactoryGirl.create(:task) forcing an employee and a company to be created as well.

What I want to do is to create valid ActiveRecord objects but with their relationships stubbed out so as to make my tests faster.

A solution I came up is to not use FactoryGirl and create the new objects using mock_model/stub_model to stub their associations.

Example:

employee = mock_model(Employee)
task = Task.create! name: "Do that", employee: employee

Am I doing it right?

Thanks.

like image 228
Nicolas Garnil Avatar asked Aug 14 '13 13:08

Nicolas Garnil


People also ask

What is ActiveRecord relation?

Whereas an instance of ActiveRecord::Relation is a representation of a query that can be run against your database (but wasn't run yet). Once you run that query by calling to_a , each , first etc. on that Relation a single instance or an array of ActiveRecord::Base instances will be returned.

What does ActiveRecord base mean?

ActiveRecord::Base indicates that the ActiveRecord class or module has a static inner class called Base that you're extending.

Can you use ActiveRecord without rails?

ActiveRecord is commonly used with the Ruby-on-Rails framework but you can use it with Sinatra or without any web framework if desired.

What is Ruby ActiveRecord?

What is ActiveRecord? ActiveRecord is an ORM. It's a layer of Ruby code that runs between your database and your logic code. When you need to make changes to the database, you'll write Ruby code, and then run "migrations" which makes the actual changes to the database.


2 Answers

If you don't want to create anything in the database you can do this:

employee = mock_model(Employee)
task = mock_model(Task, name: "Do that", employee: employee)

Keep in mind that you can't query them like that. It's roughly the same as building the object. If you ever want to do anything where you need to query actual data such as an integration test then you'll need use create to make stuff in the database. Or as one commenter pointed out, you can use FactoryGirl's methods to stub stuff out.

like image 160
Eric C Avatar answered Sep 28 '22 07:09

Eric C


There is a distinct difference between mock_model and stub_model.

Assuming you're using RSpec, check out Mock Model and Stub Model.

Briefly though, the main difference is that mock_model is a true test double, that acts like an AR model. stub_model will create an instance of an actual AR model.

Either one of these options, along with Eric C's code snippet, is a good way to isolate your tests from the DB.

like image 20
Adrian CB Avatar answered Sep 28 '22 07:09

Adrian CB