首页 文章

Rails 3.1,RSpec:测试模型验证

提问于
浏览
67

我已经在Rails中使用TDD开始了我的旅程,并且遇到了一个关于模型验证测试的小问题,我似乎无法找到解决方案 . 假设我有一个用户模型,

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

和一个简单的测试

it "should require a username" do
  User.new(:username => "").should_not be_valid
end

这正确地测试了状态验证,但如果我想更具体一点怎么办?例如,在errors对象上测试full_messages .

it "should require a username" do
  user = User.create(:username => "")
  user.errors[:username].should ~= /can't be blank/
end

我对初始尝试的关注(使用should_not be_valid)是RSpec不会产生描述性错误消息 . 它只是说“预期有效?返回虚假,变为现实” . 但是,第二个测试示例有一个小缺点:它使用create方法而不是new方法来获取errors对象 .

我希望我的测试更具体地说明他们正在测试什么,但同时不必触摸数据库 .

有人有任何意见吗?

7 回答

  • 0

    首先,我想说你有一个邪恶的名字 .

    第二,祝贺你在ROR上努力进入TDD我保证一旦你开始,你就不会回头了 .

    最简单快速和肮脏的解决方案是在每个测试之前生成一个新的有效模型,如下所示:

    before(:each) do
        @user = User.new
        @user.username = "a valid username"
     end
    

    但我建议您为所有模型设置工厂,自动为您生成有效模型,然后您可以混淆各个属性并查看是否验证 . 我喜欢使用FactoryGirl

    基本上一旦你设置好你的测试就会看起来像这样:

    it "should have valid factory" do
        FactoryGirl.build(:user).should be_valid
    end
    
    it "should require a username" do
        FactoryGirl.build(:user, :username => "").should_not be_valid
    end
    

    哦,你在这里a good railscast解释这一切比我好:

    祝好运 :)


    更新:截至version 3.0,工厂女孩的语法已更改 . 我修改了我的示例代码以反映这一点 .

  • 3

    测试模型验证(以及更多活动记录)的更简单方法是使用像shouldaremarkable这样的gem .

    他们将允许进行如下测试:

    describe User
    
      it { should validate_presence_of :name }
    
    end
    
  • 16

    试试这个:

    it "should require a username" do
      user = User.create(:username => "")
      user.valid?
      user.errors.should have_key(:username)
    end
    
  • 0

    在新版本的rspec中,你应该使用expect,否则你会得到警告:

    it "should have valid factory" do
        expect(FactoryGirl.build(:user)).to be_valid
    end
    
    it "should require a username" do
        expect(FactoryGirl.build(:user, :username => "")).not_to be_valid
    end
    
  • 42

    我传统上处理功能或请求规范中的错误内容规范 . 所以,例如,我有一个类似的规范,我将在下面简要说明:

    Feature Spec Example

    before(:each) { visit_order_path }
    
    scenario 'with invalid (empty) description' , :js => :true do
    
      add_empty_task                                 #this line is defined in my spec_helper
    
      expect(page).to have_content("can't be blank")
    

    那么,我的模型规范测试是否有效,但后来我的功能规范测试错误消息的确切输出 . 仅供参考,这些功能规格要求Capybara可以找到here .

  • 0

    就像@nathanvda所说,我会利用Thoughtbot的Shoulda Matchers gem . 通过摇摆,您可以按以下方式编写测试,以测试状态,以及任何自定义错误消息 .

    RSpec.describe User do
    
      describe 'User validations' do
        let(:message) { "I pitty da foo who dont enter a name" }
    
        it 'validates presence and message' do
         is_expected.to validate_presence_of(:name).
          with_message message
        end
    
        # shorthand syntax:
        it { is_expected.to validate_presence_of(:name).with_message message }
      end
    
    end
    
  • 96

    这里派对有点晚了,但如果你不想添加shoulda匹配器,这应该适用于rspec-rails和factorybot:

    # ./spec/factories/user.rb
    FactoryBot.define do
      factory :user do
        sequence(:username) { |n| "user_#{n}" }
      end
    end
    
    # ./spec/models/user_spec.rb
    describe User, type: :model do
      context 'without a username' do
        let(:user) { create :user, username: nil }
    
        it "should NOT be valid with a username error" do
          expect(user).not_to be_valid
          expect(user.errors).to have_key(:username)
        end
      end
    end
    

相关问题