-
Notifications
You must be signed in to change notification settings - Fork 59
NPE when mocking a trait with a NonEmpyString argument #250
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
Comments
I'll take a look |
The issue seems to be that the refined type is a value class, for which you need to specify the type when you use an any matcher. when(helloRefined.greet(refineMV[NonEmpty](any[String]))) thenReturn "hello" the above example doesn't work as it expects a literal, not sure how to dynamically instantiate a non empty string. if you make it work please update your example so I can see if we can create a something to make the interaction with refined a bit smoother |
well I really don't understand the exception. I also tested with this line when(helloRefined.greet(argThat(f = { _: NonEmptyString => true }))) thenReturn "hello" and I still get the same NPE. I don't see where mockito is trying to instanciate an NES or what would cause a NPE. The stack is not helping ...
|
OK, I think I understood by splitting the code "refined" should "greet" in {
val at: NonEmptyString = argThat(f = { _: NonEmptyString => true })
// the line above fails because NES cannot be instanciated by mockito
val g: String = helloRefined.greet(at)
val s: ScalaFirstStubbing[String] =when(g)
s thenReturn "hello"
hello.greet("me") shouldBe "hello"
} |
#244 gave me an idea ... I tried this code "refined" should "greet" in {
when(helloRefined.greet(eqTo(NonEmptyString("me")))) thenReturn "hello"
when(helloRefined.greet(eqTo(NonEmptyString("you")))) thenReturn "bye"
hello.greet("me") shouldBe "hello"
hello.greet("you") shouldBe "bye"
} But the last test fails, the mock always return "hello" :-( |
I think there are 2 problems here
I just saw your last comment (I was about to suggest using an actual value), in the code you posted and in that example you are mocking a refined class but then asserting on a regular one :P Please update the code in the repo you posted so I can check it out, I tried copying that but there are some missing implicits I don't know where to get from |
OK, first good news is that we have a workaround when comparing to an actual value: import eu.timepit.refined.auto._
"refined" should "match and greet" in {
when(helloRefined.greet(NonEmptyString("me"))) thenReturn "hello"
when(helloRefined.greet(NonEmptyString("you"))) thenReturn "bye"
helloRefined.greet("me") shouldBe "hello"
helloRefined.greet("you") shouldBe "bye"
} I pushed this version of the code @sallareznov in https://github.com/tyrcho/refined-mockito-scala |
yeah, I have the feeling that the any matcher with refined types is not gonna work, mainly cause it's quite probable that any default value that it may return could be against what the refined type is checking. |
for the initial issue, how could we "tell mockito" to use another way to instanciate with I don't really understand why mockito needs to instanciate the argument type in some cases. I also tried with |
Could we somehow tell the matcher to use a default value like |
the thing is that mockito is a Java lib, so its internals don't know about the value types as they don't really exist in Java land, it just deals with the wrapped type, that's why the matcher has to go inside the value class instance. |
Yes, I guess we could have a default, or an implicit that defines that, I'll take a look after work |
Btw, we should be having this discussion in Gitter, it would be much more fluent ;) |
conclusion of the discussion on gitter: there is a workaround like this one "refined" should "greet" in {
val helloRefined = mock[RefinedHelloWorld]
when(helloRefined.greet(star)) thenReturn "hello"
helloRefined.greet("me") shouldBe "hello"
helloRefined.greet("you") shouldBe "hello"
}
implicit val defaultNes: NonEmptyString = NonEmptyString(" ")
}
object Util {
def star[T](implicit default: T): T = {
ArgumentMatchers.argThat((_: T) => true)
default
}
} sample project is updated @ https://github.com/tyrcho/refined-mockito-scala I let you guys decide if you want to implement sth to make it easier within the library (would be great !) |
I've created a very simple project to reproduce the issue : https://github.com/tyrcho/refined-mockito-scala
This line gets a NullPointerException when the test is run
Any workaround to initialize this mock ?
The text was updated successfully, but these errors were encountered: