RSpec: Defining negated matchers

Updated . Posted . Visible to the public. Repeats.

You can use RSpec::Matchers.define_negated_matcher to define a negated version of an existing matcher. This is particularly useful in composed matcher expressions or to create more expressive and meaningful matchers.

You should only negate "atomic" matchers with an unambiguous inversion. For example, have_radio_button(label) can be negated, whereas have_active_radio_button(label) should not be. Its inversion could either mean "there is a radio button with that label, but it is not active", or "there is no radio button with that label at all". Prefer using attributes in this case: have_radio_button(label, active: true).

Examples

RSpec::Matchers.define_negated_matcher :not_change, :change

describe 'A negated matcher' do
  it 'can be used to chain negated changes' do
    expect { subject.maybe_change(object) }
      .to not_change(object, :attr_1)
      .and not_change(contract, :attr_2)
  end
end
RSpec::Matchers.define_negated_matcher :an_array_excluding, :include

describe 'A negated matcher' do
  it 'can be used in a composed matcher expression' do
    expect { list.delete(5) }.to change { list }.to(an_array_excluding(5))
  end
end
RSpec::Matchers.define_negated_matcher :exclude, :include

describe 'A negated matcher' do
  it 'can be used for creating more expressive and meaningful matchers' do
    expect(list.difference([5])).to exclude(5)
  end
end
Julian
Last edit
Dominik Schöler
License
Source code in this card is licensed under the MIT License.
Posted by Julian to makandra dev (2021-12-15 14:16)