0

I can't for the life of me figure out what's going wrong here. I have a Client model and an Invoice model.

Client.rb

has_many :invoices, dependent: :destroy

Invoices.rb

belongs_to :client

I have the following client spec:

it "destroys its children upon destruction" do
  i = FactoryGirl.create(:invoice) # As per the factory, the :client is the parent of :invoice and is automatically created with the :invoice factory

  lambda {
    i.client.destroy
  }.should change(Invoice.all, :count).by(-1)
end

And here are my factories:

Client factory

FactoryGirl.define do
  factory :client do
    city "MyString"
  end
end

Invoice factory

FactoryGirl.define do
  factory :invoice do
    association :client
    gross_amount 3.14
  end
end

If I do i = FactoryGirl.create(:invoice) and afterwards i.client.destroy manually in the console, the invoice is in fact destroyed. But for some reason, the test fails, giving me "count should have been changed by -1, but was changed by 0".

What am I doing wrong?

Dennis Hackethal
  • 13,662
  • 12
  • 66
  • 115
  • Rails tests relationships pretty well itself so most people don't bother. But you can test that your relationship is being set up properly. Check out http://stackoverflow.com/questions/2673041/checking-activerecord-associations-in-rspec – chrisbulmer Jan 02 '13 at 20:14
  • Thanks, I have done that already. But just because the relationship is set up doesn't mean children get destroyed. – Dennis Hackethal Jan 02 '13 at 20:17
  • Yes, it's strange that they aren't being deleted in your test. Just an idea, have you tested that your factory is actually creating the associated object and saving it? I couldn't see any obvious errors otherwise though so it might just be RSpec being odd... – chrisbulmer Jan 02 '13 at 20:20
  • Yes, `i = FactoryGirl.create(:invoice)` in the console creates the invoice and its client perfectly fine... Strange. – Dennis Hackethal Jan 02 '13 at 20:26

1 Answers1

2

The return value of Invoice.all is an array and so database operations won't affect it. The array doesn't change when you destroy records, and should change(receiver, message) is going to just send message to the same receiver. Try either:

lambda {
  i.client.destroy
}.should change(Invoice, :count).by(-1)

or

lambda {
  i.client.destroy
}.should change{Invoice.all.count}.by(-1)
gregates
  • 6,607
  • 1
  • 31
  • 31