使用Rspec、Devise和Factory Girl测试用户模型

20

我认为我的用户工厂构建存在问题。我收到一个错误,说密码不能为空,但是在我的factories.rb文件中已经明确设置了密码。有没有人看到我可能遗漏的内容?或者规范失败的原因?我对另一个模型执行非常类似的操作,看起来很成功。我不确定这个错误是否由devise引起。

Rspec Error

User should create a new instance of a user given valid attributes
Failure/Error: User.create!(@user.attributes)
ActiveRecord::RecordInvalid:
  Validation failed: Password can't be blank
# ./spec/models/user_spec.rb:28:in `block (2 levels) in <top (required)>'

Factories.rb

Factory.define :user do |user|
  user.name                   "Test User"
  user.email                  "user@example.com"
  user.password               "password"
  user.password_confirmation  "password"
end

user_spec.rb

require 'spec_helper'

describe User do
  before(:each) do
    @user = Factory.build(:user)
  end

  it "should create a new instance of a user given valid attributes" do
    User.create!(@user.attributes)
  end
end

user.rb

class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable

  # Setup accessible (or protected) attributes for your model
  attr_accessible :email, :password, :password_confirmation, :remember_me
end
3个回答

30

在 Factory Girl 中,这个代码创建属性:

@user_attr = Factory.attributes_for(:user)

然后这将创建一个新实例:

@user = Factory(:user)

那么改变上面的内容并尝试:

User.create!(@user_attr)

从深层次来说,你尝试做的事情失败了,因为:

  • 你正在创建一个新的未保存的实例

  • 密码是一个虚拟属性

  • 实例的属性不包含虚拟属性(我猜)


不幸的是,那似乎没有起作用。我确实想构建属性,这样我就可以使用@user.attributes.merge(:name => "Whatever")轻松地操作@user进行未来测试。这就是为什么我尝试使用User.create!(@user.attributes)的原因。我尝试过使用User.create!(@user),但失败了,这次它说电子邮件和密码为空。 - ardavis
那个起作用了。这真的很有趣。我猜现在困扰我的是,我不确定为什么我的另一个似乎也能工作。我有一个“角色”模型,我做同样的事情,使用@role = Factory.build(:role),然后Role.create!(@role.attributes)。而且它似乎通过了。有趣。谢谢您先生。 - ardavis
你的测试失败了,因为虚拟属性的原因。 - apneadiving
我不熟悉虚拟属性这个术语。这与 devise 有关吗? - ardavis
1
不,它们只是达到目的的手段:基本上,在您的模型中没有password_confirmation列。请参阅此处以获取更多信息:http://railscasts.com/episodes/16-virtual-attributes - apneadiving
1
谢谢apneadiving,我很感激你的帮助。 - ardavis

7
我认为最简单的方法是:

最简单的方法是:

FactoryGirl.modify do
  factory :user do
    after(:build) { |u| u.password_confirmation = u.password = ... }
  end
end

5

有一个对我很有效的提示。我曾使用FactoryGirl.create(:user)但它没有起作用。将其更改为以下内容:

user = FactoryGirl.build(:user)
user.password = "123456"
user.save
post :login, {:email => user.email, :password => "123456"}
# do other stuff with logged in user

这可能是因为“password”是一个虚拟字段。希望这能给某些人提供提示。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接