Rails 3.1, RSpec: testing model validations

后端 未结 7 1543
不知归路
不知归路 2021-01-30 03:51

I have started my journey with TDD in Rails and have run into a small issue regarding tests for model validations that I can\'t seem to find a solution to. Let\'s say I have a U

相关标签:
7条回答
  • 2021-01-30 04:23

    Try this:

    it "should require a username" do
      user = User.create(:username => "")
      user.valid?
      user.errors.should have_key(:username)
    end
    
    0 讨论(0)
  • 2021-01-30 04:27

    in new version rspec, you should use expect instead should, otherwise you'll get warning:

    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
    
    0 讨论(0)
  • 2021-01-30 04:31

    I have traditionally handled error content specs in feature or request specs. So, for instance, I have a similar spec which I'll condense below:

    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")
    

    So then, I have my model spec testing whether something is valid, but then my feature spec which tests the exact output of the error message. FYI, these feature specs require Capybara which can be found here.

    0 讨论(0)
  • 2021-01-30 04:31

    Like @nathanvda said, I would take advantage of Thoughtbot's Shoulda Matchers gem. With that rocking, you can write your test in the following manner as to test for presence, as well as any custom error message.

    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
    
    0 讨论(0)
  • 2021-01-30 04:33

    CONGRATULATIONS on you endeavor into TDD with ROR I promise once you get going you will not look back.

    The simplest quick and dirty solution will be to generate a new valid model before each of your tests like this:

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

    BUT what I suggest is you set up factories for all your models that will generate a valid model for you automatically and then you can muddle with individual attributes and see if your validation. I like to use FactoryGirl for this:

    Basically once you get set up your test would look something like this:

    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
    

    Oh ya and here is a good railscast that explains it all better than me:

    good luck :)


    UPDATE: As of version 3.0 the syntax for factory girl has changed. I have amended my sample code to reflect this.

    0 讨论(0)
  • 2021-01-30 04:35

    A little late to the party here, but if you don't want to add shoulda matchers, this should work with rspec-rails and 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
    
    0 讨论(0)
提交回复
热议问题