6

我对测试相当陌生,并且有一个要测试的 UsersController。我从新动作开始,到目前为止有以下内容;

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

到目前为止,我的 UsersController 看起来像这样

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

我希望我的第一个测试能够工作,但是当我运行它时,我得到以下结果;

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

在控制台中玩耍会发现以下内容;

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

所以现在我很好奇为什么 2 个空的 ActiveRecord 对象不相等(毕竟Array.new == Array.new返回 true),以及我必须做些什么才能使我的测试通过。

4

2 回答 2

6

您可能应该将测试更改为以下内容:

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

你也会有同样的效果。如果两个对象没有被保存,它们就没有主键,Rails 将使用 object_id 相等性来比较它们,这就是它们不是==的原因。

于 2012-06-03T13:31:53.227 回答
1

Activerecord 相等主要是关于两个对象是否对应于同一数据库行(例如,对应于同一行的两个实例相等,即使您开始更改其中一个的属性)。

如果您调用User.new两次并保存每个对象,您最终会在数据库中得到 2 个不同的行。因此,对我来说,他们不应该平等是有道理的。

就您的测试而言,您可以做两件事。一种是检查分配的用户是否为用户并且未保存。

另一种方式是类似的东西

User.should_receive(:new).and_return(@user)
get :new
assigns(:user).should == @user
于 2012-06-03T13:37:38.800 回答