Flexible matcher class

Due to rspec-expectations, it is dead easy to define simple custom matcher in RSpec. The matchers even can be used in a concise macro like notation.
In the case the matcher logic complexity increases there is the approach to create a custom matcher class. That also applies for custom matchers that have to be available in other Ruby testing environments like MiniTest.

A class and its spec

First of all the starting point: a Product spec, which tests an alias:

# support/matchers/alias_method_matcher.rbclassAliasMethodMatcherdefinitialize(original_method)@original_method=original_methodenddefwith(alias_method)@alias_method=alias_methodselfenddefmatches?(subject)raise'No aliased method provided'if@alias_method.nil?subject.method(@original_method)==subject.method(@alias_method)enddeffailure_message"Expected ##{@original_method} to be aliased by ##{@alias_method}, but it is not"enddeffailure_message_when_negated"Expected ##{@original_method} to not be aliased by ##{@alias_method}, but it is"enddefdescription"#{@alias_method} should be an alias of method #{@original_method}"endend

The matcher benefits from a simple technique. Setter methods (with) are made chainable by returning the matcher object itself.
The comparing matches? is called at the very end of the chain automatically.
A helper function has to return the instantiated matcher object:

The helper alias_method returns an instance of AliasMethodMatcher. The matcher object receives the message with with the argument to_s. This method also returns the matcher object (self). At the end of the it block, matches? is sent to the matcher object automatically and the comparison takes place.

The spec helper

In the case the custom matcher should not be required explicitly in each spec, it can be included globally in the spec helper: