【问题标题】:Save a factory after build, with RSpec, FactoryGirl and Rails 3.2使用 RSpec、FactoryGirl 和 Rails 3.2 在构建后保存工厂
【发布时间】:2013-06-10 21:30:58
【问题描述】:

我有一个带有 has_secure_password 的 Account 模型(它会自动创建 2 个 attr_accessors:password 和 password_confirmation,创建时需要)。我想避免在更新帐户对象时指定这些字段,因此我尝试使用 RSpec 和 factoryGirl 创建一个测试,如下所示:

describe Account do
    before do
        @account = FactoryGirl.build(:account) # this does not save the object
    end

    describe "password is not present (on update)" do
        before do
            @account.save
            @account.name = 'updated without specifying the password field'
        end
        it "should be valid" do
            should be_valid
        end
    end
end

但是,我最终得到了错误:

   Account password is not present (on update) should be valid
      Failure/Error: should be_valid
        expected valid? to return true, got false
      # ./spec/models/account_spec.rb:48:in `block (3 levels) in <top (required)>'

我无法使用 FactoryGirl.create(:account),因为 before 块在许多其他测试之前执行,并且模型验证了电子邮件字段的唯一性。


如果我在最初的 before 块中使用 FactoryGirl.create(:account)(我现在正在使用序列生成器来创建唯一的电子邮件地址)...此测试失败:

describe "email is already taken" do
    before do
      same_user = @account.dup
      same_user.email = @account.email.upcase # let's test against case sensitive strings
      same_user.save
    end

    it { should_not be_valid }
  end

这些是 Account 模型中的一些验证:

 validates :name, :surname, presence: true
  validates :email, presence: true,
                    uniqueness: { case_sensitive: false },
                    format: { with: /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i }
  validates :birthday, presence: true

  # Password validations
  validates :password, presence: true, :on => :create
  validates :password, length: { minimum: 4, maximum: 20 }, allow_blank: true
  validates :password_confirmation, presence: true, :unless => lambda { self.password.blank? }

【问题讨论】:

  • 为什么不使用序列生成器为每个对象生成唯一的电子邮件?
  • 你是对的。我已经添加了代码。谢谢

标签: ruby-on-rails rspec factory-bot


【解决方案1】:

这将在您每次使用工厂创建/建立帐户时生成一个唯一的电子邮件地址

sequence(:unique_email) {|n| "email#{n}@example.com" }
factory :account do
  email { generate(:unique_email) }
end

您不必保存对象来检查有效性

describe "email is already taken" do
    before do
      same_user = @account.dup
      same_user.email = @account.email.upcase # let's test against case sensitive strings
      same_user.valid?
    end

    it { should_not be_valid }
  end

【讨论】:

  • 我已添加您的代码,谢谢。但现在我有另一个问题:看看最初的帖子。 ;)
  • 更新了答案。对象。有效吗?填充对象上的错误。我不知道 rspec 是否调用有效?方法内部或者如果它只是检查错误属性。如果它调用有效?方法,您可以从块前删除最后一行
  • 我确实必须使用 same_user.should_not 修改 should_not 语句才能使其正常工作。终于,测试通过了!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-14
相关资源
最近更新 更多