Home > front end >  Rspec expect( ) vs expect { }
Rspec expect( ) vs expect { }

Time:09-03

Hi I am new to rspec and was trying to figure out what is the difference between passing a block to expect{ } and just using expect( )

Here is a trivial example

require "rails_helper"
RSpec.describe "Test",type: :model do
 it "testing count" do
   arr=[1,2,3]
   expect{arr<<1}.to change{arr.count}.by(1)
 end
end

This runs fine but when I do this instead

    require "rails_helper"
    RSpec.describe "Test",type: :model do
      it "testing count" do
        arr=[1,2,3]
        expect(arr<<1).to change{arr.count}.by(1)
      end
    end

It throws an error

Failures:

  1) Test testing count
     Failure/Error: expect(arr<<1).to change{arr.count}.by(1)
       expected `arr.count` to have changed by 1, but was not given a block
     # ./spec/models/test_spec.rb:6:in block (2 levels) in <top (required)>

And even when I don't use a block with change it gives me an error

require "rails_helper"
RSpec.describe "Test",type: :model do
  it "testing count" do
    arr=[1,2,3]
    expect{arr<<1}.to change(arr.count).by(1)
  end
end

Failures:

  1) Test testing count
     Failure/Error: expect{arr<<1}.to change(arr.count).by(1)
     
     ArgumentError:
       `change` requires either an object and message (`change(obj, :msg)`) or a block (`change { }`). You passed an object but no message.

Can someone explain why is it happening??

CodePudding user response:

The expect(...) syntax is used to expect that the return value of the statement in the parentheses matches a certain condition, like:

expect(result).to eq(3)
expect(list).not_to be_empty
expect(string).to match(/regexp/)
expect(1..10).to cover(3)

The expect { ... } runs the block and doesn't really care about the return value of the block, but instead about the side-effects of running the code in the block. Like that another value changes by running the block or that an exception is raised.

expect { api_request }.to raise_error(NotFoundError)
expect { object.action }.to change(object, :value).from(old).to(new)
expect { actual }.to output("some output").to_stdout

Find more examples in the RSpec docs

In your example

expect { array << 1 }.to change { array.count }.by(1)

because a side-effect of pushing a value into an array is that the count of elements in the array changes. But

expect(array << 1).to change { arr.count }.by(1)

does not work, because the return value of expect(array << 1) is [1, 2, 3, 1] and this syntax does not support the change matcher.

  • Related