Custom Matchers

Learn how to define your own matchers to extend ScalaTest DSL.

In this lesson, we’ll take a look at custom matchers. We’ll start off by refining the way we use property and boolean matchers and then define our own.

Property matchers

We can define custom property matchers by creating instances of the HavePropertyMatcher trait. ScalaTest documentation advises doing this in a trait we can later mix into our test classes. The following snippet of code defines custom matchers for Course#title, Course#author, and PaidCourse#price.

Press + to interact
import mdipirro.educative.io.effectiveunitandintegrationtestinginscala.model.{Author, Course, PaidCourse}
import org.scalatest.matchers.{HavePropertyMatchResult, HavePropertyMatcher}
trait CoursePropertyMatchers:
def title(expectedValue: String): HavePropertyMatcher[Course, String] =
new HavePropertyMatcher[Course, String]:
def apply(course: Course) =
HavePropertyMatchResult(
matches = course.title == expectedValue,
propertyName = "title",
expectedValue = expectedValue,
actualValue = course.title
)
def author(expectedValue: Author): HavePropertyMatcher[Course, Author] =
(course: Course) => HavePropertyMatchResult(
matches = course.author == expectedValue,
propertyName = "author",
expectedValue = expectedValue,
actualValue = course.author
)
trait PaidCoursePropertyMatchers extends CoursePropertyMatchers:
def price(expectedValue: BigDecimal): HavePropertyMatcher[PaidCourse, BigDecimal] =
(course: PaidCourse) => HavePropertyMatchResult(
matches = course.price == expectedValue,
propertyName = "price",
expectedValue = expectedValue,
actualValue = course.price
)

A custom property matcher is simply a method whose name is the name of the matcher, returning an instance of HavePropertyMatcher[Course, String] (lines 6, 16, and 25). This method simply binds the name of a property in the target class (Course in this case) to the apply method of HavePropertyMatcher.

The second type parameter (for example, String in HavePropertyMatcher[Course, String]) represents the type of the expected value. In the example above, the title matcher (line 5) is shown with verbose syntax. This syntax can be sugared to use a single abstract method, as shown in ...