ScalaTest matchTo to support matching Options
Closed this issue · 2 comments
Hi, I get a compilation error when i.e.
import com.softwaremill.diffx.scalatest.DiffMatcher
callMethodThatReturnsOption(...) should matchTo(Some(x))
it works fine for sequences. Weirdly it works fine with code like
Some(5) should matchTo(Some(5)) but not if the left part is a method invocation.
On scala 2.13 and these deps:
val ScalaTest = ivy"org.scalatest::scalatest:3.2.0"
val Diffx = Seq(ivy"com.softwaremill.diffx::diffx-core:0.3.29", ivy"com.softwaremill.diffx::diffx-scalatest:0.3.29")
Hi,
The reason why it works for:
Some(5) should matchTo(Some(5))
and doesn't work for:
def method: Option[Int] = Some(5)
method should matchTo(Some(5))
Is that, in the first case both type parameters are fixed to be Some
while in the second case one is Option
and the other is Some
. Of course Some <: Option
for given T
and because Diff
is contravariant following is also true: Diff[Option[T] <: Diff[Some[T]]
. Matcher[T]
from scalatest is also contravariant so Matcher[Option[T]] <: Matcher[Some[T]]
, but I am guessing that compiler ins't extrapolating types here to find out that Option
would be the correct supertype because the should
method is overloaded and it seems that overloading has bigger priority than types' extrapolation.
TLDR: I have no idea how to fix that apart from helping compiler to choose the right method by specifying the type of the matcher explicitly:
Option(left) should matchTo[Option[Foo]](Some(right))
Alternatively if you use cats, you can do:
Option(left) should matchTo(right.some)
as .some
returns Option
Ok I see, thanks. So as a workaround I am using it like
myMethod(...) should matchTo(Option(5)) // Note: Option(5) not Some(5), this now compiles