Understanding RSpec Expect and Change Syntax in the context of Ruby

Let’s look at how this syntax works for RSpec in the context of the Ruby Language.

http://rspec.info/documentation/3.2/rspec-expectations/RSpec/Matchers.html#change-instance_method

https://www.relishapp.com/rspec/rspec-expectations/v/3-2/docs/built-in-matchers/change-matcher

expect {
  team.add_player(player)
}.to change(roster, :count)
expect {
  team.add_player(player)
}.to change { roster.count }
  1. expect is a method call that takes a block. The block can use either {} or do end as the bock will be bound to the expect method calll regardless.

  2. The result of calling expect with a block is then called with the to (or not_to) method, passing in either 2 parameters or a block. From the docs is this incredibly important statement:

You can either pass receiver and message, or a block, but not both.

  1. When pass a block to change, it’s critical to use {} syntax and NOT do end syntax as the lower precedence of the do end will result in the block being bound to the call to to or not_to rather than change.

  2. Definitely use spaces around the {} as they look too much like () parens.

Take a look at the samples below. Consider how you could switch between the two syntaxes.

I created a video where I walk through this example:

Some examples of the syntax:

expect {
  team.add_player(player)
}.to change(roster, :count)

expect {
  team.add_player(player)
}.to change(roster, :count).by(1)

expect {
  team.add_player(player)
}.to change(roster, :count).by_at_least(1)

expect {
  team.add_player(player)
}.to change(roster, :count).by_at_most(1)

string = "string"
expect {
  string.reverse!
}.to change { string }.from("string").to("gnirts")

string = "string"
expect {
  string
}.not_to change { string }.from("string")

expect {
  person.happy_birthday
}.to change(person, :birthday).from(32).to(33)

expect {
  employee.develop_great_new_social_networking_app
}.to change(employee, :title).from("Mail Clerk").to("CEO")

expect {
  doctor.leave_office
}.to change(doctor, :sign).from(/is in/).to(/is out/)

user = User.new(:type => "admin")
expect {
  user.symbolize_type
}.to change(user, :type).from(String).to(Symbol)