RSpec and Factory Girl: Destroying an object

Hi,

I have a problem when testing the deletion of a record from the
database. I am using RSpec methods to check if my account object is
being destroyed.

The factory creates an account object and saves it into the DB. Also
the two should_receive expectations seem to work.

The problem is that when checking the database after the
“delete :destroy, :id => account” line, the account record still
exists.

it "should be able to destroy an account" do
  account = Factory(:account)
  Account.should_receive(:find).and_return(account)
  account.should_receive(:destroy)

  delete :destroy, :id => account

  Account.all.should == []
  response.should be_success
  response.should render_template("new")
end

app/controllers/accounts_controller.rb

def destroy
account = Account.find(params[:id])
account.destroy

redirect_to accounts_path

end

I hope someone can help me on this one.

Thanks

On May 14, 2010, at 8:09 AM, Daniel Salmeron A. wrote:

“delete :destroy, :id => account” line, the account record still
Account.all.should == []
end

I hope someone can help me on this one.

You’ve mocked out the call to destroy, which hides the original
implementation. Pick either a state-based test (checking the database,
don’t use mocks) or mock-based test, but don’t mix and match.

Pat

Hey Pat, thanks for replying.

How would you test this method? Checking the database or mocking? Is
there any advantage of using one over the other ?

I don’t really understand the benefits of using mocks, so could you
tell me how would you write the test using both methods (mocking, and
checking the DB? Could you explain me the advantages of using mocking
and advantages of checking de DB?

Thank you very much,

Dani

Daniel Salmeron A. wrote:

How would you test this method? Checking the database or mocking? Is
there any advantage of using one over the other ?

Hi, Dani.

You originally wrote that you want “to check if my account object is
being destroyed.” I can think of a few reasons to check this:

  1. I don’t yet know Rails well and want to check that I understand how
    #destroy works.
  2. I don’t trust Rails to destroy an object correctly.
  3. I’ve configured some behavior of my object in a way that might cause
    Rails to destroy it differently than I expect.
  4. I think I’ve found a bug in Rails.

Do you want to check the destroy method for one of these reasons, or
something else entirely? I ask, because that information guides me to
choose one of three options:

  1. Check #destroy by invoking it directly.
  2. Check a client by stubbing/mocking #destroy.
  3. Don’t check #destroy at all.

Since I didn’t write #destroy, I prefer not to check it. (Principle:
Don’t Test The Platform.) If I don’t trust #destroy, I check it by
invoking it directly, because I think there might be a bug in Rails. If
I don’t understand what #destroy does, I check it by invoking it
directly, because I’m writing Learning Tests. (Principle: Write examples
to check your assumptions about how someone else’s code works.)

I don’t really understand the benefits of using mocks, so could you
tell me how would you write the test using both methods (mocking, and
checking the DB? Could you explain me the advantages of using mocking
and advantages of checking de DB?

I think of it this way: if I want to check #destroy, I invoke it
directly with the database; but if I want to check that my code asks to
destroy an object at the right time, I mock #destroy; and finally, if I
want to check that my code reacts appropriately after destroying an
object, then I stub #destroy. To understand some of the underlying
principles, I humbly recommend this:
http://jbrains.ca/integrated_tests_are_a_scam (The articles are in order
from newest first, so start at the end).

Enjoy.