由于之前的测试,Rspec单元测试失败

时间:2014-02-05 20:13:02

标签: ruby-on-rails ruby unit-testing rspec

我是Rspec的新手,我正在为一个旧项目进行测试。我在设置变量方面遇到了问题。基本上,我的User对象受先前测试中的操作的影响。 我有一个简单的用户工厂:

FactoryGirl.define do
    factory :user do
        first_name 'Bob'
        last_name 'Shabbadoo'
        office
        login 'lurker48'
        email 'test.user@test.com'
        password 'TestWhatNots#21'
        password_confirmation{|u| u.password}
    end
end

然后我进行了实际的rspec测试。

require "spec_helper"

describe User do

    it 'has a valid factory' do
        FactoryGirl.build(:user).should be_valid
    end

  describe '#password' do

    it "cannot contain the word 'password'" do
        valid_user = FactoryGirl.build(:user)
        valid_user.password << "password"
        valid_user.password_confirmation = valid_user.password
        valid_user.should_not be_valid
    end

    it "cannot contain the users last_name" do
        valid_user = FactoryGirl.build(:user)
        valid_user.password << valid_user.last_name
        valid_user.password_confirmation = valid_user.password
        valid_user.should_not be_valid
    end

    it "cannot contain the users first_name" do
        valid_user = FactoryGirl.build(:user)
        valid_user.password << valid_user.first_name
        valid_user.password_confirmation = valid_user.password
        valid_user.should be_valid
    end
  end

end

我故意使“无法包含用户first_name”测试失败 正如我所料,我得到了这个:

User
  has a valid factory
  #password
    cannot contain the word 'password'
    cannot contain the users last_name
    cannot contain the users first_name (FAILED - 1)

但是当我仔细查看密码时,它看起来像这样:

TestWhatNots#21passwordShabbadooBob

为什么先前测试中的操作会污染信息?

1 个答案:

答案 0 :(得分:0)

当您构建新的用户对象时,工厂女孩会将其密码分配给给定字符串(它是String类的实例)。每次执行此操作时,您的用户密码都指向该对象 - 如果您构建两个用户,则他们的密码不仅相同 - 它们是相同的对象。

使用<<方法更改此对象,因此您正在更改此工厂已经或将要创建的所有对象的密码值。

 u1 = FactoryGirl.build(:user)
 u2 = FactoryGirl.build(:user)

 u1.password.object_id == u2.password.object_id   #=> true!

解决方案:

选项1.不要修改对象,而是分配新的字符串对象:

valid_user.password += valid_user.first_name

选项2.将所有值包装在一个块中。这将强制FactoryGirl在每次构建新对象时运行块,从而创建单独但相同的String实例:

factory :user do
    first_name { 'Bob' }
    last_name { 'Shabbadoo' }
    ...