Rails 5.1 introduced assert_changes and assert_no_changes

Narendra Rajput avatar

Narendra Rajput

May 9, 2017

This blog is part of our  Rails 5.1 series.

Rails 5.1 has introduced assert_changes and assert_no_changes. It can be seen as a more generic version of assert_difference and assert_no_difference.

assert_changes

assert_changes asserts the value of an expression is changed before and after invoking the block. The specified expression can be string like assert_difference.


@user = users(:john)
assert_changes 'users(:john).status' do
  post :update, params: {id: @user.id, user: {status: 'online'}}
end

We can also pass a lambda as an expression.


@user = users(:john)
assert_changes -> {users(:john).status} do
  post :update, params: {id: @user.id, user: {status: 'online'}}
end

assert_changes also allows options :from and :to to specify initial and final state of expression.


@light = Light.new
assert_changes -> { @light.status }, from: 'off', to: 'on' do
  @light.turn_on
end

We can also specify test failure message.


@invoice = invoices(:bb_client)
assert_changes -> { @invoice.status }, to: 'paid', 'Expected the invoice to be marked paid' do
  @invoice.make_payment
end

assert_no_changes

assert_no_changes has same options and asserts that the expression doesn't change before and after invoking the block.

Follow @bigbinary on X. Check out our full blog archive.