I use nulls explicitly in tests to designate parameters that shouldn’t be used by tested logic. In general, NPEs in tests are exceptions like any other exception - they allow us to find problems quickly, before things go to production. OTOH exceptions in production code are evil as they can break user experience. Treating exceptions in production and exceptions in tests differently is the only sane way to use them effectively, I think.
Mockito relies heavily on reflection so there should be no problem for Mockito to supply None
s instead of null
s (if that’s what you want) . Here’s my quick stab at it:
package mocking
import org.mockito.{Answers, Mockito}
import org.mockito.invocation.InvocationOnMock
import org.mockito.stubbing.Answer
import scala.util.Try
object NonesForNulls {
trait Behavior {
def greet(): Unit
}
case class Struct(fieldOpt: Option[Integer] = None,
none: None.type = None,
field: Behavior)
def main(args: Array[String]): Unit = {
println("With default settings:")
val mock1 = Mockito.mock(classOf[Struct])
println(mock1.fieldOpt)
println(mock1.none)
println(mock1.field)
println("...added Option[_] and None awareness:")
val mock2 = Mockito.mock(
classOf[Struct],
optionAwareAnswer(Answers.RETURNS_DEFAULTS)
)
println(mock2.fieldOpt)
println(mock2.none)
println(mock2.field)
println("With smart nulls:")
val mock3 = Mockito.mock(classOf[Struct], Answers.RETURNS_SMART_NULLS)
println(mock3.fieldOpt)
println(mock3.none)
println(mock3.field)
Try(mock3.field.greet()).failed.foreach(_.printStackTrace(System.out))
println("...added Option[_] and None awareness:")
val mock4 = Mockito.mock(
classOf[Struct],
optionAwareAnswer(Answers.RETURNS_SMART_NULLS)
)
println(mock4.fieldOpt)
println(mock4.none)
println(mock4.field)
Try(mock4.field.greet()).failed.foreach(_.printStackTrace(System.out))
}
// this method is probably wrong
// I haven't tested Options in nested mocks
def optionAwareAnswer(delegate: Answer[AnyRef]): Answer[AnyRef] = {
invocation: InvocationOnMock =>
val returnType = invocation.getMethod.getReturnType
if (returnType.isAssignableFrom(None.getClass)) {
None
} else {
delegate.answer(invocation)
}
}
}
There’s mockito-scala
library so maybe that was already done.