Reputation: 281
I have a piece of code that I want to test:
class User < ActiveRecord::Base
has_many :servers, :dependent=> :destroy
end
Please give an example of RSpec code that tests the association code.
Upvotes: 5
Views: 4367
Reputation: 454
For simple spec examples/generations i would recommend using the gem regressor:
https://github.com/ndea/regressor
This gem will generate some simple specs for your model based on relations/validations/database/callbacks on which you can orientate your future specs.
Upvotes: 0
Reputation: 3515
I present two approaches: the quick and dirty, and the D.R.Y and clean :)
The quick and dirty:
context "when testing dependent: destroy" do
before do
@user = User.create
@servers = [Server.create]
@user.servers = @servers
end
it "should destroy all of the associated servers" do
@servers.each{|s| Server.exists?(s.id).should be_false}
end
end
To do this in a DRY and reusable fashion, with only a dependence on rspec itself, you need a custom matcher for HasMany. The high level spec will look like this:
Subject { User.new }
it { should have_many :tasks, dependent: :destroy }
Then the matcher will look as follows:
RSpec::Matchers.define :have_many do |_association, opts|
if opts and opts[:dependent]
match do |model|
associations(model, :has_many, opts).any? { |a| a == _association }
end
failure_message_for_should do |model|
error(
:expected => [ "%s to have many %s and to have dependent => :destroy %s", model, _association, opts[:dependent] ],
:actual => [ "%s has many %s ", model, associations(model, :has_many) ]
)
end
else
match do |model|
associations(model, :has_many).any? { |a| a == _association }
end
failure_message_for_should do |model|
error(
:expected => [ "%s to have many %s", model, _association ],
:actual => [ "%s has many %s", model, associations(model, :has_many) ]
)
end
end
end
You will need this rspec helper module: http://pastie.org/6356719
I like the first approach even though its dirty because it goes to the database and uses the full rails stack...but someone people think thats too coupled. The second approach is more dry but requires a helper that just introspects onto the association itself and may not cover other problems that may screw up the deletion of associated objects...
Upvotes: 1
Reputation: 2918
For me this variant works well:
describe User do
it { should have_many(:servers).dependent(:destroy) }
end
Upvotes: 8
Reputation: 47
Here I use Factory girl:
it "should be destroyed when user is destroyed" do
@user.servers << @server
@user.destroy
Server.all.should_not include(@server)
end
But you can also create a new user in the test like this:
it "should be destroyed when user is destroyed" do
user = User.create(:name => "Julia")
user.servers << Server.create(:server_name => "Julias server")
user.destroy
Server.all.should_not include("Julias server")
end
Upvotes: 1
Reputation: 16197
While answering your current question might help you right now, what you really need is to understand Testing.
You want to write a test for a piece of code that you have already there. With a TDD methodology, you will do the opposite: First you write the test, then you write the code that makes that test pass.
I will recommend that you buy The RSpec Book, by the Pragmatic Programmers. It will explain you very clearly what you should be doing and how. Really good book, worth every penny.
Another answer says that you should be using Shoulda. While that is a good practice, try to do it first by yourself. Once you understand what you should do, then you can use an abstraction like Shoulda.
The other answer uses a Factory. While that is a good practice, I would recommend that you first use the RSpec built-in tools, like Mock objects and stub methods. Once you understand how these two operates, then you can use an abstraction like Factories. By the way, Fabrication is simpler.
Upvotes: 4
Reputation: 181
One way of testing associations in RSpec is using shoulda. Shoulda is a collection of helpers that make common repetitive tests quick to write whilst being understandable. To test your model, make sure the shoulda gem is installed and required. Then you can test your association with something like the following:
describe User do
it {should have_many :servers, :dependent => :destroy}
end
Upvotes: 0