I am fairly new to testing and have a UsersController that I want to test. I am starting with the new action and so far have the following;
require 'spec_helper'
describe UsersController do
describe "GET 'new'" do
it "assigns a new User to @user" do
user = User.new
get :new
assigns(:user).should eq(user)
end
it "renders the :new template"
end
end
My UsersController so far looks like this
class UsersController < ApplicationController
def new
@user = User.new
end
end
I expected my first test to work but when I run it I get the following;
Failures:
1) UsersController GET 'new' assigns a new User to @user
Failure/Error: assigns(:user).should eq(user)
expected: #<User id: nil, email: nil, username: nil, password_digest: nil, created_at: nil, updated_at: nil>
got: #<User id: nil, email: nil, username: nil, password_digest: nil, created_at: nil, updated_at: nil>
(compared using ==)
Diff:#<User:0x007fe4bbfceed0>.==(#<User:0x007fe4bce5c290>) returned false even though the diff between #<User:0x007fe4bbfceed0> and #<User:0x007fe4bce5c290> is empty. Check the implementation of #<User:0x007fe4bbfceed0>.==.
# ./spec/controllers/users_controller_spec.rb:9:in `block (3 levels) in <top (required)>'
Playing around in the console reveals the following;
irb(main):001:0> a = User.new
=> #<User id: nil, email: nil, username: nil, password_digest: nil, created_at: nil, updated_at: nil>
irb(main):002:0> b = User.new
=> #<User id: nil, email: nil, username: nil, password_digest: nil, created_at: nil, updated_at: nil>
irb(main):003:0> a == b
=> false
So now I'm curious as to why 2 empty ActiveRecord objects are not equal (after all, Array.new == Array.new
returns true), and what I have to do to make my test pass.
You should probably change your test to something like this:
describe UsersController do
describe "GET 'new'" do
it "assigns a new User to @user" do
get :new
assigns(:user).should be_new_record
assigns(:user).kind_of?(User).should be_true
end
it "renders the :new template" end
end
And you will have the same effect. If two objects aren't saved, they don't have primary keys to Rails is going to use object_id equality to compare them, that's why they're not ==.
Activerecord equality is largely about whether the two objects correspond to the same database row (for example two instances corresponding to the same row are equal, even of you start changing the attributes of one of them).
If you call User.new
twice and saved each object you would end up with 2 distinct rows in the database. To me it therefore makes sense that they shouldn't be equal.
In terms of your test you could do 2 things. One is to check that the assigned user is a user and that it is unsaved.
Another way is something along the lines of
User.should_receive(:new).and_return(@user)
get :new
assigns(:user).should == @user
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With