Godzilla74
Godzilla74

Reputation: 2512

Testing if association exists in rspec

I'm new to using rspec, so hopefully I'm explaining this correctly. I want to make sure my object is created and afterwards make sure that a related object with a has_one relationship is created.

So, my code would look like this in the model:

class Device < ActiveRecord::Base
  has_one :scan_option

  validates_presence_of :name

  after_create :create_scan_option

  def create_scan_option
    self.scan_option.create!
  end
end

I have a Factory for a device:

FactoryGirl.define do
  serial_number = SecureRandom.uuid.delete("-")

  factory :device do
    identifier serial_number
    name "Device 1"
    is_registered true
    timezone "America/Chicago"
  end
end

In my rspec model test I imagine the code would look like this:

RSpec.describe Device, :type => :model do
  it "creates a scan_option after_create" do
    subject = build(:device)
    # test whether the scan_option object was created and associated with the device?
  end
end

I'm not using shoulda or anything, just trying to understand Rspec better.

Upvotes: 0

Views: 2072

Answers (3)

spickermann
spickermann

Reputation: 107132

I would do something like this:

subject(:device) { Device.create(attributes_for(:device)) }

it 'has a scan option' do
  expect(device.scan_option).to be_present
end 

I would use Device.create instead of FactoryGirl.create to ensure that the class itself creates the associated object and that it is not created by the factory.

Upvotes: 2

leifg
leifg

Reputation: 9028

Several Ways:

subject = build(:device)
expect(subject.scan_option).not_to be_nil

expect { build(:device) }.to change(ScanOption, :count).by(1)

It probably won't pass because you only built your factory.

In order for the callback to be executed you actually have to persist it in the database:

subject = create(:device)

Upvotes: 0

j-dexx
j-dexx

Reputation: 10416

You should just be able to save the device and then call the association and check it returns something

it "creates a scan_option after_create" do
    subject = build(:device)

    subject.save

    expect(subject.scan_option).to be
end

Upvotes: 0

Related Questions