paulbutcher / ScalaMock

Native Scala mocking framework
http://scalamock.org/
MIT License
501 stars 98 forks source link

Compiler error when mocking classes with generics #170

Open barkhorn opened 7 years ago

barkhorn commented 7 years ago

worked in 3.4.2, broken in 3.5.0

real example:

      class MockableBroadcast[T: ClassTag] extends org.apache.spark.broadcast.Broadcast[T](42L) {
        override protected def getValue(): Nothing = ???
        override protected def doUnpersist(blocking: Boolean): Unit = ???
        override protected def doDestroy(blocking: Boolean): Unit = ???
      }
      val lookup= mock[MockableBroadcast[Map[String, Long]]]

minified example:

      class Foo[T: ClassTag]
      val mf = mock[Foo[Nothing]]

compiler error:

Error:(55, 20) type mismatch;
 found   : scala.reflect.ClassTag[T]
 required: scala.reflect.ClassTag[Nothing]
Note: T >: Nothing, but trait ClassTag is invariant in type T.
You may wish to investigate a wildcard type such as `_ >: Nothing`. (SLS 3.2.10)
      val mf = mock[Foo[Nothing]]
barkhorn commented 7 years ago

cause: changes to MockMaker.initDef in e07cca308abaebdaeeca27c3c2933bdc211f3bcc

barkhorn commented 7 years ago

https://github.com/paulbutcher/ScalaMock/blob/88504cc7a0a519324680df17b1a96b7aa71720a5/core/shared/src/main/scala/org/scalamock/clazz/MockMaker.scala#L222

typeSignatureIn returns the parameter T, not the materialised type (e.g. Int)

barkhorn commented 7 years ago

Bit stuck on this one, so I asked at https://stackoverflow.com/questions/42044540/obtaining-the-realised-type-for-a-scala-class-using-macros and gitter

barkhorn commented 7 years ago

very stuck, the solution with .dealias is more difficult to implement than I thought. Also MockAdapter for 2.10 redirects this to .normalize

kell18 commented 11 months ago

Hello, is there maybe any workaround for this one? It's quite painful... Thanks!

kell18 commented 11 months ago

Okay, I found workaround, you need to specify all the types (including _ in F[_]) explicitly by creating another class which extends from the generic one