【问题标题】:Rails Rspec Model Spec User :email ActiveRecord::RecordInvalidRails Rspec 模型规范用户:电子邮件 ActiveRecord::RecordInvalid
【发布时间】:2012-08-08 06:31:19
【问题描述】:

试图找出我的 rspec 测试失败的原因。最值得注意的是看似矛盾的失败消息。说我有一个 ActiveRecord::RecordInvalid 错误,这正是我断言应该发生的。

这是我的 user.rb

...
validates_presence_of :email
...

这是我的 users_spec.rb

...
it "is invalid without email" do 
  Factory(:user, email: nil).should raise_error(ActiveRecord::RecordInvalid)
end
...

这是输出:

Failures:

  1) User a user (in general) is invalid without email
     Failure/Error: Factory(:user, email: nil).should raise_error(ActiveRecord::RecordInvalid)
     ActiveRecord::RecordInvalid:
       Validation failed: Email is invalid, Email can't be blank
     # ./spec/models/user_spec.rb:34:in `block (3 levels) in <top (required)>'

最初我是这样测试的,但它一直失败,所以我决定说明我所期望的错误。

it "is invalid without email" do 
  Factory(:user, email: nil).should_not be_valid
end

【问题讨论】:

    标签: ruby-on-rails ruby rspec


    【解决方案1】:

    您的代码无法正常工作的原因是您在实际测试其有效性之前尝试创建一个无效模型。您要做的是创建一个有效的模型,更改某些内容并检查它是否无效,如下所示:

    it "is invalid without email" do 
      user = Factory(:user)
      user.email = nil
      user.should_not be_valid
    end
    

    我个人喜欢在before 块中定义我的模型,设置为subject,然后更改每个规范中的属性并检查有效性,如下所示:

    before do
      @user = FactoryGirl.create(:user)
    end
    
    subject { @user }
    
    it "is invalid without email" do
      subject.email = nil
      should_not be_valid
    end
    

    为了记录,如果您想测试记录创建是否引发了错误(这绝对是这样做的可取的方法),您可以通过包装Factory 调用来做到这一点在lambda 中,像这样:

    lambda {
        Factory(:user, :email => nil)
    }.should raise_error(ActiveRecord::RecordInvalid)
    

    【讨论】:

    • 谢谢,这完全有道理。你觉得 let!(:user) { Factory(:user)} 而不是 before do ... end?
    • 顺便说一句,您为什么不建议将其包装在 lambda {} 或期望 {} 中?
    • 我的意思是我不建议通过检查是否引发错误来检查有效性。使用lambda 检查在其他上下文中是否引发错误是完全可以的。
    猜你喜欢
    • 2015-05-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-18
    • 1970-01-01
    • 2016-08-16
    • 1970-01-01
    相关资源
    最近更新 更多