Unit testing validates_associated and HABTM relationships

I'm trying to set up some unit tests and they are failing on just basic tests on one model.

The failure is:

1) Failure: test_invalid_with_empty_attributes(WorkAreaTaskTest) [test/unit/work_area_task_test.rb:15]: <false> is not true.

My model is:

class WorkAreaTask < ActiveRecord::Base

  belongs_to :task   belongs_to :work_area   has_many :employee_tasks, :dependent => :destroy

  acts_as_list :scope => :work_area

  validates_presence_of :task_id   validates_presence_of :work_area_id

  validates_presence_of :task   validates_associated :task

end

And my unit test is:

class WorkAreaTaskTest < Test::Unit::TestCase   fixtures :work_area_tasks, :employee_type_tasks, :tasks, :work_areas

  # Replace this with your real tests.   def test_truth     assert true   end

  def test_invalid_with_empty_attributes      work_area_task = WorkAreaTask.new

     assert !work_area_task.valid?      assert work_area_task.errors.invalid?(:task_id)      assert work_area_task.errors.invalid?(:work_area_id)      assert work_area_task.errors.invalid?(:task)    end end

The failure occurs at the assert invalid tests.

Can’t tell from your posting which line is line 15. Where exactly is it failing?

It's failing on this line:

assert work_area_task.errors.invalid?(:task_id)

The only way to get it to not fail is to comment that line and the next 2 as well. So it's like is getting the the IDs and the task from somewhere, because they should be empty.

I don’t know why you are checking the id’s. The id’s are usually keys that are generated automatically when you save the model. Is there any reason why you are validating id’s?

If you cannot save the model, the id fields will be blank.

I'm not checking the id's from the model I am testing. I am checking the foreign key id's, ie. the id's from the related tables that need to be there for the model to be valid. That's why I am checking for them.

Read this first: http://manuals.rubyonrails.com/read/chapter/27

Test the behavior, not the implementation. You don’t have to check the foreign keys. You can save a valid record and read it back and compare it with fixture data. It is very similar to the example from the above tutorial. Remove validates_presence_of :task_id, :work_area_id from your model class. I would love to be proved wrong here.

Ahhh. I see what you are saying. Rooky mistake on my part. :slight_smile:

So basically the belongs_to is going to take care of the foreign keys, so there's no reason for me to have "validates_X_of" for them is what you are saying?

Yes. Also before you start writing tests, jot down specifications in a sheet of paper. Then write : test_should_your_written_specification_one, two etc. When you do TDD really well you are actually thinking in terms of behavior.

If you really want to push the envelope and have some time to kill, then check out rSpec. There is a nice Google video that was presented at Google about rSpec.

For your viewing pleasure: http://video.google.com/videoplay?docid=8135690990081075324&q=bdd&hl=en