Function Testing Reloading Fixtures before assertion

Hey Everyone, I have a function test the is failing (despite the fact the function actually works in the application). I was looking for some debug advice on how to find my problem.

Here is the test:   def test_should_delete_word     assert_equal 'published', words(:one).status     debugger     delete :destroy, :id => words(:one).to_param

    assert_equal 'deleted', words(:one).status   end

It fails on the last with: <"deleted"> expected but was <"published">.

//My fixture: one:   word: cup   was_created_by_user: true   status: published   user_id: 1   ip_address: '129.1.0.0'

//Controller: def destroy     @word = Word.find(params[:id], :include => :definitions)     @word.status = 'deleted'     @word.save

    @word.definitions.each do |h|       h.status = 'deleted'       h.save     end

    respond_to do |format|       format.html { redirect_to(words_url) }     end   end

Now the actually application works just like expected changes all appropriate columns in the db.

I think the problem is that after I run the delete method in the test the fixtures are reloaded before the next assert so the status is put back to "published" when it should be "deleted". I think this is the problem only because when I step through the process in the debugger I see:    force_reload = fixtures.pop if fixtures.last == true || fixtures.last == :reload Right after it calls the delete.

Any help would be appreciated. - bp

I think the problem is that after I run the delete method in the test the fixtures are reloaded before the next assert so the status is put back to "published" when it should be "deleted". I think this is the problem only because when I step through the process in the debugger I see:

It's the opposite problem: fixtures are not reloaded, so although the copy in the database now has status deleted words(:one) is now a stale object - you just need to reload it before making testing whether it's status has changed.

Fred

Frederick Cheung wrote:

Frederick Cheung wrote: It's crap like this that has put me off fixtures. Try something like Machinist instead. Fixtures just don't work for many common testing scenarios.

anything that uses actual activerecord objects can have this sort of issue because you can have 2 entirely separate objects that represent the same row in the database.

Fred

Here is the test:   def test_should_delete_word     assert_equal 'published', words(:one).status     debugger     delete :destroy, :id => words(:one).to_param         assert_equal 'deleted', words(:one).status   end

It fails on the last with: <"deleted"> expected but was <"published">.

if i understand correctly your problem here is you are checking values from fixture instead of database like this assert_equal 'deleted', words(:one).status

instead you must check your status from database

assert_equal 'deleted', check value from database not from fixture

Hey everyone thanks for the input.

I've tried your suggestions with varying results:

def test_should_delete_word     assert_equal 'published', words(:one).status     debugger     delete :destroy, :id => words(:one).to_param     Word.reload     word_status=Word.find(:id).status     assert_equal 'deleted', word_status end Returns reload is not method.

I tried def test_should_delete_word2       assert_equal 'published', words(:one).status       delete :destroy, :id => words(:one).to_param

      assert_equal 'deleted', Word.find(:id.to_param).status   end It claims "Couldn't find Word with ID=id" same with assert_equal 'deleted', Word.find(:id).status

I also tried using Machinist but really don't know what objects to call on to try anything. Wouldn't I have to first create a word then find the word delete the ford and check the value. At that point it sounds more like an integration test then Functional.   def test_should_delete_word     word = Word.plan     delete :destroy, :id => word.id // Returns cannot find id as the object was never stored?     assert_equal 'deleted', assigns(:id).status   end

Thanks for your suggestions so far

Returns reload is not method.

sorry for wrong syntax

it must be reload!

you are using Word.find(:id.to_param).status in assert instead of that use "Word.find_by_user_id(1).status" ( as per your fixture in first post)

Hey everyone thanks for the input.

I've tried your suggestions with varying results:

def test_should_delete_word assert_equal 'published', words(:one).status debugger delete :destroy, :id => words(:one).to_param Word.reload word_status=Word.find(:id).status assert_equal 'deleted', word_status end Returns reload is not method.

reload is a method on an individual activerecord object (ie words (:one).reload)

Fred

Hey, thanks again for the help, I've given it another one but come up with pretty much the same errors. (side note the strings I was asserting to are now symbols)

  def test_should_delete_word     assert_equal :published, words(:one).status     delete :destroy, :id => words(:one).to_param     reload!     word_status = Word.find(:id).status     assert_equal :deleted, word_status   end Again returns: MethodError: undefined method `reload!' for #<WordsControllerTest:0x2858368>

I also tried reloading on the active record object directly

  def test_should_delete_word2     assert_equal :published, words(:one).status     delete :destroy, :id => words(:one).to_param     words(:one).reload (as well as reload!)     word_status = Word.find(:id).status     assert_equal :deleted, word_status   end It returns: ActiveRecord::RecordNotFound: Couldn't find Word with ID=id

Eventually it worked with(just a last attempt before I posted):

  def test_should_delete_word2     assert_equal :published, words(:one).status     delete :destroy, :id => words(:one).to_param     words(:one).reload     word_status = Word.find(words(:one)).status     assert_equal :deleted, word_status   end

Which I find a little weird. Just because in this and other tests I've found the fixtures produce weird id's when they hit the db. The only way I can find matching id's is with the to_param string. So why Word.find(words(:one)) managed to find a matching ID in the db without using to_param beats me.

But thanks for everyones input ! If you have any idea about the id's I wouldn't mind understanding exactly what is going on there.

-bp

I also tried reloading on the active record object directly

def test_should_delete_word2 assert_equal :published, words(:one).status delete :destroy, :id => words(:one).to_param words(:one).reload (as well as reload!) word_status = Word.find(:id).status

That doesn't make a whole load of sense - unless there had been a word whose id was the string id.

assert\_equal :deleted, word\_status

end It returns: ActiveRecord::RecordNotFound: Couldn't find Word with ID=id

Eventually it worked with(just a last attempt before I posted):

def test_should_delete_word2 assert_equal :published, words(:one).status delete :destroy, :id => words(:one).to_param words(:one).reload word_status = Word.find(words(:one)).status assert_equal :deleted, word_status end

Which I find a little weird. Just because in this and other tests I've found the fixtures produce weird id's when they hit the db. The only way I can find matching id's is with the to_param string. So why Word.find(words(:one)) managed to find a matching ID in the db without using to_param beats me.

because find knows the right thing to do if you give it an activerecord object. You can do either words(:one).reload and then look at words (:one).status or look at Word.find(words(:one)).status but you don't need to do both - that's just redundant.

Fred

Nilesh,

using:      assert_equal :published, words(:one).status      delete :destroy, :id => words(:one).to_param      word_status = Word.find(:id).status      assert_equal :deleted, word_status still returns // ActiveRecord::RecordNotFound: Couldn't find Word with ID=id

Fred, I see what you mean now. If I wanted to pull the information from the db instead of the fixture then there was no point in taking the time to reload the stale fixture. Now that we've reloaded it I can feel free to test against then fresh data. This function now passes without problem and it makes sense:   def test_should_delete_word     assert_equal :published, words(:one).status     delete :destroy, :id => words(:one).to_param     words(:one).reload     assert_equal :deleted, words(:one).status   end

Again thanks everyone for your input !