Mohamad
Mohamad

Reputation: 35349

How do you test a model that is dependent on another?

I have User, Account, and Role models. A User can exist by itself. An Account must be tied to a User through a Role. An Account must have at least one Role record of type "Owner". I'm not sure how to test this in RSpec and FactoryGirl.

# user_id, account_id, role
Role < ActiveRecord::Base
  belongs_to :user
  belongs_to :account
end

User < ActiveRecord::Base
  has_many :roles
  has_many :accounts, through: roles
  accepts_nested_properties_for :accounts
end

Account < ActiveRecord::Base
  has_many :roles
  has_many :users, through: roles
end

If a user is not signed in, the Accounts.new will display the User and Account forms. If a user is signed in, only the Account form will be displayed. The trouble is, I'm unsure what Role and Account will look like in RSpec when trying to test the associations.

This test fails (the array comes back empty):

describe Account do
  let(:user) { FactoryGirl.create(:user) }
  before { @account = user.accounts.build(title: "ACME Corporation", subdomain: "acme") }
  subject { @account }
  it { should respond_to(:users) }
  its(:users) { should include(user) }

Then there is the added complication of testing when users are signed in, and when they are not. Any reference sample code I can see for a similar use case? I'm also not sure what to test for in roles_spec, and what belongs to accounts_spec/user_spec.

Factories:

FactoryGirl.define do
  factory :user do
    name                  "Mickey Mouse"
    email                 "[email protected]"
    password              "m1ckey"
    password_confirmation "m1ckey"
  end
  factory :account do
    title     "ACME Corporation"
    subdomain "acme"
  end
  factory :role do
    user
    account
  end
end

Upvotes: 0

Views: 310

Answers (1)

Robert Harvey
Robert Harvey

Reputation: 180788

You test objects that depend on other objects by using a mocking framework to "mock" the other objects. There are a number of mock frameworks that allow you to do this.

Upvotes: 1

Related Questions