Skip to content

Unable to use value classes for answers in idiomatic API #168

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Closed
mikolak-net opened this issue Oct 28, 2019 · 5 comments · Fixed by #170
Closed

Unable to use value classes for answers in idiomatic API #168

mikolak-net opened this issue Oct 28, 2019 · 5 comments · Fixed by #170

Comments

@mikolak-net
Copy link

mikolak-net commented Oct 28, 2019

When running the following code on 1.6.2:

package com.example.test

import org.mockito.{ ArgumentMatchersSugar, IdiomaticMockito }
import org.scalatest.{ FlatSpec, Matchers }

class AnyValMockReproSpec extends FlatSpec with Matchers with IdiomaticMockito with ArgumentMatchersSugar {
  val WString = "foo"

  it should "return a prefixed value for `any` mock" in {
      val decoder = mock[Decoder]
      decoder.decode(any[ValueClass]) answers ((v: ValueClass) => v.value)

      val tested = new Prefixer(decoder)

      tested.prefix(ValueClass(WString)) should be(s"prefix-$WString")
    }

  it should "return a prefixed value for `*` mock" in {
      val decoder = mock[Decoder]
      decoder.decode(*) answers ((v: ValueClass) => v.value)

      val tested = new Prefixer(decoder)

      tested.prefix(ValueClass(WString)) should be(s"prefix-$WString")
    }
}

case class ValueClass(value: String) extends AnyVal

trait Decoder {
  def decode(v: ValueClass): String
}

class Prefixer(decoder: Decoder) {
  def prefix(v: ValueClass): String = s"prefix-${decoder.decode(v)}"
}

the result is the following:

AnyValMockReproSpec:
- should return a prefixed value for `any` mock *** FAILED ***
  java.lang.ClassCastException: java.lang.String cannot be cast to com.example.test.ValueClass
  at com.example.test.AnyValMockReproSpec.$anonfun$new$2$adapted(AnyValMockReproSpec.scala:11)
  at org.mockito.package$.$anonfun$functionToAnswer$1(mockito.scala:30)
  at scala.Function1.$anonfun$andThen$1(Function1.scala:57)
  at org.mockito.stubbing.ScalaAnswer$$anon$2.answer(ScalaAnswer.scala:13)
  at org.mockito.internal.stubbing.StubbedInvocationMatcher.answer(StubbedInvocationMatcher.java:39)
  at org.mockito.internal.handler.MockHandlerImpl.handle(MockHandlerImpl.java:96)
  at org.mockito.internal.handler.ScalaMockHandler.handle(ScalaMockHandler.scala:37)
  at org.mockito.internal.handler.ScalaNullResultGuardian.handle(ScalaNullResultGuardian.scala:11)
  at org.mockito.internal.handler.InvocationNotifierHandler.handle(InvocationNotifierHandler.java:35)
  at org.mockito.internal.creation.bytebuddy.MockMethodInterceptor.doIntercept(MockMethodInterceptor.java:61)
  ...
- should return a prefixed value for `*` mock *** FAILED ***
  java.lang.NullPointerException:
  at com.example.test.AnyValMockReproSpec.$anonfun$new$3(AnyValMockReproSpec.scala:20)
  at org.scalatest.OutcomeOf.outcomeOf(OutcomeOf.scala:85)
  at org.scalatest.OutcomeOf.outcomeOf$(OutcomeOf.scala:83)
  at org.scalatest.OutcomeOf$.outcomeOf(OutcomeOf.scala:104)
  at org.scalatest.Transformer.apply(Transformer.scala:22)
  at org.scalatest.Transformer.apply(Transformer.scala:20)
  at org.scalatest.FlatSpecLike$$anon$5.apply(FlatSpecLike.scala:1682)
  at org.scalatest.TestSuite.withFixture(TestSuite.scala:196)
  at org.scalatest.TestSuite.withFixture$(TestSuite.scala:195)
  at org.scalatest.FlatSpec.withFixture(FlatSpec.scala:1685)

It appears the function serving as the mocked method receives an unwrapped value that is then cast into a value class.

The second case might actually be unrelated to this problem (and may be another issue), included nevertheless for completeness' sake.

@ultrasecreth
Copy link
Member

That's an interesting one (the first one), I have an idea on what the problem is but will probably take a couple of days to be fixed.
For the second one check https://github.com/mockito/mockito-scala#value-class-matchers

@mikolak-net
Copy link
Author

@bbonanno : thanks for the answer! Regarding the second point - ah, completely missed that, sorry. Shall I remove this case from the report, for clarity?

@ultrasecreth
Copy link
Member

@mikolak-net That's all right, otherwise I'd also have to change my comment :)
I'll try to fix this value class issue as soon as I can, thanks for reporting it!

@ultrasecreth
Copy link
Member

Version 1.7.0 should solve it!

@mikolak-net
Copy link
Author

That was fast, thanks!

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants