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 !