I have a method in a class:
def delete(Token, Client, Scope): Future[Int]
and this method is called elsewhere in another class inside another method as:
acr.delete(Token(token), client, scope)
where token
is a String
and client
and scope
are types of Client
and Scope
respectively:
case class Client(client: String) extends AnyVal
case class Scope(scope: String) extends AnyVal
When I try to mock the delete
method in my test, I do it as :
when(mockService
.delete(
token = any[Token],
service = any[Client],
scope = any[Scope]
)
).thenReturn(1.toFut)
which yields a Matching Exception which causes a Null Pointer Exception:
Method threw 'org.mockito.exceptions.misusing.InvalidUseOfMatchersException' exception. Cannot evaluate repositories.common.Service$MockitoMock$1804616202.toString()
mockService
is a mock[Service]
. I have another method mocked, belonging to Service
and that mock does not throw any errors
When I debug it line-by-line, the code fails on the token = any[Token]
line. I'm not sure how else I can use Matchers
and construct a mock.
What do you suggest I do?
I assume your code looks the same as:
case class Token(client: String) extends AnyVal
case class Client(client: String) extends AnyVal
case class Scope(scope: String) extends AnyVal
class Service(implicit val ec: ExecutionContext) {
def delete(token: Token, client: Client, scope: Scope): Future[Int] = {
Future(1)
}
}
and for this code, you can create Token
as Token[any[String]]
import org.mockito.ArgumentMatchers.any
import org.mockito.Mockito.when
import org.mockito.MockitoSugar.mock
import scala.concurrent.{ExecutionContext, Future}
implicit val ec: ExecutionContext = ExecutionContext.global
val mockService: Service = mock[Service]
when(
mockService.delete(
token = Token(any[String]),
client = Client(any[String]),
scope = Scope(any[String])
)
).thenReturn(Future(2))
this code works and doesn't throw NPE.
I have assumption: your code throws NPE because case classes extends AnyVal
.
Let's look at AnyVal
source code:
abstract class AnyVal extends Any {
def getClass(): Class[_ <: AnyVal] = null
}
it has getClass
which returns null
- that sounds not null-safety. If you will remove extends AnyVal
from your case classes, your code will work. Probably any
matcher call getClass
inside itself, so it's a usual things for testing libraries.