Search code examples
ruby-on-railsrspecrspec-railsreusability

Rspec, multiple assertions over the same code


I'm trying to check multiple conditions over the same execution, in this case is just a post( :create , user: user.attributes ) but I would like to know in general what's the best approach.

Here is the complete example

describe UsersController do
describe 'CRUDL' do
    describe 'create' do
        let(:user) { User.new(username: "created") }
        let(:response) {  post( :create , user: user.attributes ) }


        it 'should respond with created(201) http message' do
            response.code.should == "201"
        end
        it 'should increment total users count' do
            expect{ response }.to change{User.count}.by(1)
        end
    end
end

The expect{ response }.to change{User.count}.by(1) part does not seem right. What would be the correct approach to test many assertion over the same code execution?


Solution

  • A word of caution, if you are using rspec-rails, there is already a response method add into the example object. Patching a custom let on top may result in difficult to debug errors.

    With that being said, there isn't anything wrong with these tests. You should be only testing one thing per spec, which you are. The expect{}.to change{} part may seem weird because your let(:response) is both the action you want to test and the storage of the response object.

    It may make more intuitive sense to have something like:

    describe 'CRUDL' do
      context 'creating a user' do
        let(:normal_user) { User.new(username: "created") }
    
        def create_user(user)
          post( :create , user: user.attributes )
        end
    
        it 'responds with created(201) http message' do
          create_user normal_user
    
          expect(response.code).to eq '201'
        end
    
        it 'creates the user' do
          expect{ create_user normal_user }.to change{User.count}.by(1)
        end
      end
    end