Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ambiguous implicit conversions causing compile failure in Scalatest and Argonaut.io

I'm currently doing that most noble of programming endeavors, writing tests for Json encoding / decoding. I'm using Argonaut.io for Json and Scalatest for my testing framework. Under scalatest, the use of === during assertion verification provides additional information if a failure occurs, while the use of ==simply gives this org.scalatest.exceptions.TestFailedException was thrown.. However, the scala compiler is not happy. Here's the code:

val default = new Broadcast("default", "default", "default")
test("Should parse out network when present") {
  val hcursor = testHCursor(jsonPath + "complete-broadcast.json")
  val actualNetwork = Parser.BroadcastDecodeJson(hcursor)
    .getOr(default)
    .network
  assert(actualNetwork === "ESPNU")
}

That spews out this:

[info] Compiling 1 Scala source to /home/vagrant/waltercamp/waltercamp-dataservice/target/scala-2.10/test-classes...
[error] /home/vagrant/waltercamp/waltercamp-dataservice/src/test/scala/io/ptx/waltercamp/schedules/BroadcastParserSuite.scala:16: type mismatch;
[error]  found   : actualNetwork.type (with underlying type String)
[error]  required: ?{def ===(x$1: ? >: String("ESPNU")): ?}
[error] Note that implicit conversions are not applicable because they are ambiguous:
[error]  both method ToEqualOps in trait ToEqualOps of type [F](v: F)(implicit F0: scalaz.Equal[F])scalaz.syntax.EqualOps[F]
[error]  and method convertToEqualizer in trait Assertions of type (left: Any)BroadcastParserSuite.this.Equalizer
[error]  are possible conversion functions from actualNetwork.type to ?{def ===(x$1: ? >: String("ESPNU")): ?}
[error]     assert(actualNetwork === "ESPNU")
[error]            ^
[error] one error found
[error] (test:compile) Compilation failed

The use == however provides a clean compilation and pass. Is there a way provide the compiler a hint as to which conversion, or the conversion order, to use?

like image 802
penland365 Avatar asked Oct 31 '22 18:10

penland365


1 Answers

I'd go with ScalaTest's version here. One approach would be to apply the conversion explicitly:

assert(convertToEqualizer(actualNetwork) === "ESPNU")

That's kind of unpleasant, though, and involves a lot of repetitious boilerplate if you're using === many times in a file. Another way would be to exclude the Scalaz conversion from the general import:

import scalaz._, Scalaz.{ ToEqualOps => _, _ }

You could also switch to à la carte imports for Scalaz and just be sure you don't pull in ToEqualOps via scala.syntax.equal._. I'll admit I find à la carte imports a pain to maintain sometimes, but if you're not doing much with Scalaz in the test this wouldn't be too bad.

like image 115
Travis Brown Avatar answered Nov 11 '22 10:11

Travis Brown