Rails RSpec Tests for a has_many :through Relationship
I'm new to testing and rails but i'm trying to get my TDD process down properly.
I was wondering if you use any 开发者_开发问答sort of paradigm for testing has_many :through relationships? (or just has_many in general i suppose).
For example, i find that in my model specs i'm definitely writing simple tests to check both ends of a relationship for relating methods.
ie:
require 'spec_helper'
describe Post do
before(:each) do
@attr = { :subject => "f00 Post Subject", :content => "8ar Post Body Content" }
end
describe "validations" do
...
end
describe "categorized posts" do
before(:each) do
@post = Post.create!(@attr)
end
it "should have a categories method" do
@post.should respond_to(:categories)
end
end
end
Then in my categories spec i do the inverse test and check for @category.posts
What else am i missing? thanks!!
I would recommend checking out a gem called Shoulda. It has a lot of macros for testing things like relationships and validations.
If all you want is to test that the has_many relationship exists, then you could do the following:
describe Post do
it { should have_many(:categories) }
end
Or if you're testing a has_many :through, then you'd use this:
describe Post do
it { should have_many(:categories).through(:other_model) }
end
I find the Shoulda Rdoc page very helpful too.
For the sake of completeness, in 2020 this is possible without additional gems.
it "has many categories" do
should respond_to(:categories)
end
And even more explicit:
it "belongs to category" do
t = Post.reflect_on_association(:category)
expect(t.macro).to eq(:belongs_to)
end
(see Ruby API on Reflection)
The second example makes sure that a "has_one" is not confused with a "belongs_to" and vice versa
It is, however, not limited to has_many :through relationships, but can be used for any association applied to the model.
(Note: This is using the new rspec 2.11 syntax with Rails 5.2.4)
remarkable will do this nicely:
describe Pricing do
should_have_many :accounts, :through => :account_pricings
should_have_many :account_pricings
should_have_many :job_profiles, :through => :job_profile_pricings
should_have_many :job_profile_pricings
end
Generally, you just copy all of your relationships from the model to the spec and change "has" to "should_have", "belongs_to" to "should_belong_to", and so on. To answer the charge that it's testing rails, it checks the database also, making sure that the association works.
Macros are also included for checking validations as well:
should_validate_numericality_of :amount, :greater_than_or_equal_to => 0
describe "when Book.new is called" do
before(:each) do
@book = Book.new
end
#otm
it "should be ok with an associated publisher" do
@book.publisher = Publisher.new
@book.should have(:no).errors_on(:publisher)
end
it "should have an associated publisher" do
@book.should have_at_least(1).error_on(:publisher)
end
#mtm
it "should be ok with at least one associated author" do
@book.authors.build
@book.should have(:no).errors_on(:authors)
end
it "should have at least one associated author" do
@book.should have_at_least(1).error_on(:authors)
end
end
精彩评论