Search⌘ K
AI Features

Custom Matchers

Explore how to create custom property and boolean matchers in ScalaTest to make your test cases more expressive and type-safe. Understand how custom matchers improve test readability and reusability by encapsulating complex conditions, and learn best practices for integrating them into your Scala unit tests.

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.

Scala
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 ...