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

时间:2022-11-20 00:15:25

I'm new to Rspec and I'm putting in tests for an old project. I'm having issues with setting variables. Bascially my User object is affected by actions in previous tests. I have a simple user factory:

我是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

Then I have my actual rspec tests.

然后我有我的实际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

I purposefully made the "cannot contain the users first_name" test fail and as I expected I got this:

我有目的地使“不能包含用户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)

But when I took a closer look a the password it looked like this:

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

TestWhatNots#21passwordShabbadooBob

Why would actions in previous tests taint the information?

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

1 个解决方案

#1


0  

When you build new user object, factory girl assigns to its password given string (it is, to the instance of String class). Every time you do this, you user password is pointing to that object - if you build two users, their password are not only identical - the are the same object.

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

By using << method youre altering this object and hence you are altering password value for all objects which have been or will be created by this factory.

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

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

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

Solutions:

解决方案:

Option 1. Do not modify the object but assign a new string object instead:

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

valid_user.password += valid_user.first_name

Option 2. Wrap all your values within a block. This will force FactoryGirl to run block each time you build new object and hence to create separate but identical String instances:

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

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

#1


0  

When you build new user object, factory girl assigns to its password given string (it is, to the instance of String class). Every time you do this, you user password is pointing to that object - if you build two users, their password are not only identical - the are the same object.

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

By using << method youre altering this object and hence you are altering password value for all objects which have been or will be created by this factory.

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

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

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

Solutions:

解决方案:

Option 1. Do not modify the object but assign a new string object instead:

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

valid_user.password += valid_user.first_name

Option 2. Wrap all your values within a block. This will force FactoryGirl to run block each time you build new object and hence to create separate but identical String instances:

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

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