1

They say the perfect test just includes the test framework and the class being tested; everything else should be mocked. Then, what about associations?

And I don't mean simple has_many, belongs_to associations, but association extensions and scopes. I'd really like to write specs for scopes, but I just can't figure how to do it.

Erik Escobedo
  • 2,793
  • 24
  • 42

1 Answers1

1

I got caught up on this too. In Rspec, they get rid of the idea of "Unit Tests". In practice, unit tests in Rails means, at least to me, testing the attribute values on a model. But you're right, what about associations?

In Rspec you just create a spec/models directory, and test your models. At the top of a model spec (spec/models/user_spec.rb), you have your unit tests (testing your attributes), then you test each association below:

require 'spec_helper'

describe User do
  context ":name" do
    it "should have a first name"
    it "should have a last name"
  end

  # all tests related to the gender attribute
  context ":gender" do
    it "should validate gender"
  end

  # all tests related to "belongs_to :location"
  context ":location" do
    it "should :belong_to a location"
    it "should validate the location"
  end

  # all tests related to "has_many :posts"
  context ":posts" do
    it "should be able to create a post"
    it "should be able to create several posts"
    it "should be able to list most recent posts"
  end
end

But now you're testing the Post and Location models in your User tests? Yep. But the Post model is going to have a bunch of extra stuff outside of what it does in relation to the user. Same with Location. So you'd have a spec/models/location_spec.rb like:

require 'spec_helper'

describe Location do
  context ":city" do
    it "should have a valid city"
  end

  context ":geo" do
    it "should validate geo coordinates"
  end
end

None of that should be mocked in my opinion. At some point you have to actually test the associations are saving and are queryable. That's here. Think about it as, in the model specs, you have "Unit Test" for attributes and "Integration Tests" for associations.

Lance
  • 75,200
  • 93
  • 289
  • 503
  • 1
    Very good explanation, thank's for that! I would like to add that you should have the following rules additionally: test the part of the association you have in the model (user -> comment == test, who to create, get, delete from the user object perspective); don't that `ActiveRecord` works, only test that your usage of `ActiveRecord` works. – mliebelt Sep 17 '11 at 10:47
  • I would add to that "test the code you write yourself." If the only thing your model class does with an association is to define it, then it is sufficient to ensure that the association is defined (say, by making sure that you can access a has_many array on a fixture). If a method calls has_many#build, test your method, not the #build functionality of has_many. Don't take the approach of, "my model is providing assurances to property `posts` can do x, y, z, so I have to test that it can do x, y, z. That way lies madness. Note that specific combos of options count as "your code" for testing imo – Christopher Swasey Aug 07 '13 at 17:47