2012-06-03 18 views
6

Soy bastante nuevo para probar y tengo un UserController que deseo probar. Estoy comenzando con la nueva acción y hasta ahora tengo lo siguiente;¿Cómo pruebo la asignación de una variable de instancia en la nueva acción de mi controlador con 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 

Mi UsersController hasta ahora se ve así

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

que esperaba mi primera prueba para trabajar, pero cuando lo ejecuto me sale el siguiente;

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

Jugar en la consola revela lo siguiente;

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 

Así que ahora tengo curiosidad de por qué los objetos ActiveRecord 2 vacíos no son iguales (después de todo, Array.new == Array.new devuelve true), y lo que tengo que hacer para que mi tarjeta de prueba.

Respuesta

6

Probablemente debería cambiar su prueba a algo como esto:

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 

Y tendrá el mismo efecto. Si dos objetos no se guardan, no tienen claves primarias para que Rails vaya a usar la igualdad object_id para compararlos, es por eso que no son ==.

+2

Si el autor quiere comprobar si un registro es a la vez nuevo y no se ha definido ninguna atributos, necesitará también una comprobación de 'should_not be_changed '. – jdoe

+0

¡Excelente! No sabia sobre esto. –

+1

Gracias por eso. Eso tiene buen sentido. – brad

1

La igualdad de Activerecord se trata principalmente de si los dos objetos corresponden a la misma fila de la base de datos (por ejemplo, dos instancias correspondientes a la misma fila son iguales, incluso si comienza a cambiar los atributos de una de ellas).

Si llama al User.new dos veces y guarda cada objeto, terminaría con 2 filas distintas en la base de datos. Para mí, por lo tanto, tiene sentido que no sean iguales.

En términos de su prueba, puede hacer 2 cosas. Una es verificar que el usuario asignado sea un usuario y que no se haya guardado.

Otra forma es algo a lo largo de las líneas de

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

¡Uy! ¡Bien visto! –

Cuestiones relacionadas