...

/

Syntactic Sugar for Common Scenarios

Syntactic Sugar for Common Scenarios

Learn how to leverage ScalaTest’s syntactic sugar to test Scala’s Option, Either, and PartialFunction.

In this lesson, we’ll look into some syntactic sugar to make assertions on Option, Either, and partial functions. So far, we’ve frequently had to deal with Option and Either. In those cases, we often relied on pattern matching or explicit if expressions. There’s nothing wrong with using pattern matching or if in those cases, but in this lesson, we’ll analyze the idiomatic ScalaTest method.

Assertions on Option and Either

The simplest way to assert that an instance of Option[T] contains a valid value, different than None, is simply calling .get on it (line 16).

package mdipirro.educative.io.effectiveunitandintegrationtestinginscala.matchers

import mdipirro.educative.io.effectiveunitandintegrationtestinginscala.TestSuite
import mdipirro.educative.io.effectiveunitandintegrationtestinginscala.model.v2.{Author, Educative, FreeCourse, Lesson}
import org.scalatest.Inspectors

class EducativeSpec extends TestSuite:

  private val educative = Educative(Seq(
    FreeCourse("Scala for Beginners", Author("John", "Doe"), Set.empty[Lesson], Set.empty[String]),
    FreeCourse("Scala for Data Analysis", Author("Mary", "Jane"), Set.empty[Lesson], Set("Scala")),
    FreeCourse("Functional Kotlin", Author("Mary", "Jane"), Set.empty[Lesson], Set("kotlin"))
  ))

  it `should` "return a valid course, if it exists" in {
    val c = educative.courseByName("Scala for Beginners").get

    c.title shouldBe "Scala for Beginners"
    c.author.firstName shouldBe "John"
    c.author.lastName shouldBe "Doe"
    c.lessons shouldBe empty
    c.tags shouldBe empty
    c.price shouldBe 0
  }
Testing Options using Option#get

This is not ideal. If the returned Option is None, the error returned by ScalaTest contains very little useful information.

testOnly mdipirro.educative.io.effectiveunitandintegrationtestinginscala.matchers.EducativeSpec
[info] EducativeSpec:
[info] Educative
[info] - should return a valid course, if it exists *** FAILED *** (1 millisecond)
[info] java.util.NoSuchElementException: None.get
[info] at scala.None$.get(Option.scala:627)
[info] at scala.None$.get(Option.scala:626)
[info] at mdipirro.educative.io.effectiveunitandintegrationtestinginscala.matchers.EducativeSpec.testFun$proxy6$1(EducativeSpec.scala:57)
[info] at mdipirro.educative.io.effectiveunitandintegrationtestinginscala.matchers.EducativeSpec.$init$$$anonfun$6(EducativeSpec.scala:56)
Error message from ScalaTest

Even if the stack trace points us to a line in the test suite class, the error message is not so clear: java.util.NoSuchElementException: None.get. This is because the exception isn’t a TestFailedException but a NoSuchElementException.

We can make it more explicit using pattern matching or, better still, a fold (line 16).

package mdipirro.educative.io.effectiveunitandintegrationtestinginscala.matchers

import mdipirro.educative.io.effectiveunitandintegrationtestinginscala.TestSuite
import mdipirro.educative.io.effectiveunitandintegrationtestinginscala.model.v2.{Author, Educative, FreeCourse, Lesson}
import org.scalatest.Inspectors

class EducativeSpec extends TestSuite:

  private val educative = Educative(Seq(
    FreeCourse("Scala for Beginners", Author("John", "Doe"), Set.empty[Lesson], Set.empty[String]),
    FreeCourse("Scala for Data Analysis", Author("Mary", "Jane"), Set.empty[Lesson], Set("Scala")),
    FreeCourse("Functional Kotlin", Author("Mary", "Jane"), Set.empty[Lesson], Set("kotlin"))
  ))

  it `should` "return a valid course, if it exists" in {
    educative.courseByName("Scala for Beginners").fold(fail("A valid course was expected")) { c =>
      c.title shouldBe "Scala for Beginners"
      c.author.firstName shouldBe "John"
      c.author.lastName shouldBe "Doe"
      c.lessons shouldBe empty
      c.tags shouldBe empty
      c.price shouldBe 0
    }
  }
Testing Options using Option#fold
...