Matchers for cats EitherT and effects

757 Views Asked by At

I'm new in cats and functional programming and I'm struggling with unit testing functional data types like EitherT. Having example code:

class Library[F[_]]() {
    def create(book: Book)(implicit M: Monad[F]): EitherT[F, BookAlreadyExistsError, Book] = ...
}

I'd like to test it using Spec2 but I don't know how to do it properly. Tried something like this but it does not work:

  val library = Library[IO]()

  test("create book") {

    val book = Book("Title 1", 2016, "author 1")
    (for (
      resultBook <- library.create(book)
    ) yield resultBook shouldEqual ???
    ).unsafeRunSync()

  }

I'd like to have very simple assertions like this:

   resultBook shouldEqual Right(Book("Title 1", 2016, "author 1"))
   // or
   resultBook shouldEqual Left(BookAlreadyExistsError)
1

There are 1 best solutions below

0
Mario Galic On BEST ANSWER

specs2-cats provides IOMatchers trait which enables the following syntax

library.create(book).value must returnValue(Right(book))

where

libraryDependencies += "org.specs2" %% "specs2-core" % "4.8.1" % Test,
libraryDependencies += "org.specs2" %% "specs2-cats" % "4.8.1" % Test,

Here is a working example

import cats.data.EitherT
import cats.effect.IO
import org.specs2.mutable.Specification
import org.specs2.matcher.IOMatchers

class CatsSpec extends Specification with IOMatchers {
  case class Book(title: String, year: Int, author: String)
  def create(book: Book): EitherT[IO, String, Book] = EitherT(IO(Right(book).withLeft[String]))
  val book = Book("Title 1", 2016, "author 1")

  "specs2-cats dependency" should {
    "provide matcher for IO effect" in {
      create(book).value must returnValue(Right(book))
    }
  }
}