【问题标题】:Rails 3.1 Rspec Creating test case validate field for ModelRails 3.1 Rspec为模型创建测试用例验证字段
【发布时间】:2025-12-13 12:55:02
【问题描述】:

我正在尝试为用户模型创建一个测试用例。基本上,它将验证 first_name 和 last_name 是否存在。

我要做的是检查特定字段上的错误是否为空,它应该为空。但是总是失败。

这样做的正确方法是什么?

这是我的代码

在我的 user_spec.rb 上

require 'spec_helper'

describe User do

  before do
    @user = User.new
  end

  it "must have a first name" do
    @user.errors[:first_name].should_not be_empty
  end

  it "must have a last name" do
    @user.errors[:last_name].should_not be_empty
  end
end

在我的 user.rb 文件中

class User < ActiveRecord::Base
  validates :first_name, :presence => true
  validates :last_name, :presence => true
end

【问题讨论】:

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


    【解决方案1】:

    您也可以通过简单地进行测试:

    describe 'validations' do
      it { should validate_presence_of :firstname }
      it { should validate_presence_of :lastname  }
    end
    

    查看shoulda matchers 了解所有此类标准 Rails 验证。 这种方式不仅更简洁,而且还处理了正例。这意味着您不需要测试下面提到的场景:

    it "passed validations when first_name is set"
      user = User.create(:firstname => 'f', :lastname => 'l')
      user.errors[:first_name].should be_empty
      user.errors[:last_name].should be_empty
    end
    

    【讨论】:

    • 为未来的观众点赞。 shoulda 匹配器更适合测试验证。
    • 不要用it "should ..." do描述,最好用it { should validate_presence_of :firstname }
    • 我已经根据@moregeek 提出的新的更好的语法更新了答案
    【解决方案2】:

    RSpec 支持“隐式”主题的概念。如果“describe”块的第一个参数是一个类,RSpec 会自动为您的规范提供该类的一个实例。见http://relishapp.com/rspec/rspec-core/v/2-6/dir/subject/implicit-subject

    require 'spec_helper'
    
    describe User do
    
      it "must have a first name" do    
        subject.should have(1).error_on(:first_name)
      end
    
      it "must have a last name" do
        subject.should have(1).error_on(:last_name)
      end
    end
    

    这会导致 RSpec 输出(如果使用 --format 文档):

    User
      must have a first name
      must have a last name
    

    如果您对 RSpec 输出默认值感到满意,您可以进一步缩写它:

    require 'spec_helper'
    
    describe User do
      it { should have(1).error_on(:first_name) }
      it { should have(1).error_on(:last_name) }
    end
    

    导致:

    User
      should have 1 error on :first_name
      should have 1 error on :last_name
    

    【讨论】: