2012-06-03 9 views
6

Ich bin ziemlich neu zu testen und habe einen UsersController, den ich testen möchte. Ich beginne mit der neuen Aktion und habe bisher folgendes;Wie teste ich die Zuweisung einer Instanzvariable in der neuen Aktion meines Controllers mit rspec?

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 

Mein Userscontroller so sieht weit wie diese

class UsersController < ApplicationController 
    def new 
    @user = User.new 
    end 
end 

ich meinen ersten Test aber wahrscheinlich zu funktionieren, wenn ich es laufen bekomme ich folgende;

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)>' 

Das Herumspielen in der Konsole zeigt folgendes;

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 jetzt bin ich neugierig, warum 2 leere Active Objekte nicht gleich sind (immerhin Array.new == Array.new kehrt wahr), und was muss ich tun, um meine Testdurchlauf zu machen.

Antwort

6

Sie sollten wahrscheinlich Ihren Test so etwas wie dies ändern:

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 

Und Sie werden die gleiche Wirkung haben. Wenn zwei Objekte nicht gespeichert werden, haben sie keine Primärschlüssel, damit Rails die Gleichheit object_id verwendet, um sie zu vergleichen, deshalb sind sie nicht ==.

+2

Wenn der Autor überprüfen möchte, ob ein Datensatz beide neu und hat keine Attribute gesetzt, müssen er eine Überprüfung auch für 'should_not be_changed '. – jdoe

+0

Großartig! Ich wusste nichts davon. –

+1

Danke dafür. Das macht Sinn. – brad

1

Active Gleichheit ist weitgehend darüber, ob die beiden Objekte auf der gleichen Datenbankzeile entsprechen (zum Beispiel zwei Instanzen derselben Zeile entspricht gleich sind, auch von Ihnen die Attribute einer von ihnen zu ändern beginnen).

Wenn Sie zweimal User.new aufrufen und jedes Objekt speichern, würden Sie mit zwei verschiedenen Zeilen in der Datenbank enden. Für mich ergibt es daher Sinn, dass sie nicht gleich sein sollten.

In Bezug auf Ihren Test könnten Sie 2 Dinge tun. Eine besteht darin, zu überprüfen, dass der zugewiesene Benutzer ein Benutzer ist und dass er nicht gespeichert ist.

Ein anderer Weg ist etwas entlang der Linien von

User.should_receive(:new).and_return(@user) 
get :new 
assigns(:user).should == @user 
+0

oops - gut entdeckt! –

Verwandte Themen