Mocking a function with pass-by-name arguments - scala

My actual use-case is unit testing code involving finagle FuturePool: I want to make sure, FuturePool.apply was actually invoked, so that the task was executed in the correct instance of the pool.
The problem I am running into however seems more generic, so I will illustrate it on an abstract example, not related to finagle or futures.
Suppose, I have these two classes:
class Foo {
def apply(f: => String) = f
}
class Bar(val foo: Foo) {
def doit(f: => String) = foo(f)
}
Bar has an instance of Foo, that knows how to run functions, and I want to test that it is actually using it for execution:
describe("Bar") {
it("should use the right foo") {
val foo = mock[Foo]
when(foo.apply(any)).thenAnswer( new Answer[String] {
def answer(invocation: InvocationOnMock): String =
invocation.getArgumentAt(0, classOf[Function0[String]]).apply()
})
new Bar(foo).doit("foo") should equal("foo")
}
}
This does not work: .doit return null, apparently, because mockito does not realize it was mocked. It seems that any is not matching Function0 in this case (replacing it with any[Function0[String]] does not help either.
I also tried it another way:
it("should Foo!") {
val foo = Mockito.spy(new Foo)
new Bar(foo).doit("foo") should equal("foo")
verify(foo).apply(any)
}
This also does not work, and kinda confirms my suspicion about any not working in this case:
Argument(s) are different! Wanted:
foo$1.apply(
($anonfun$apply$mcV$sp$7) <function0>
);
Actual invocation has different arguments:
foo$1.apply(
($anonfun$apply$mcV$sp$6) <function0>
);
Any ideas about a good way to get around this?

This signature:
def apply(f: => String)
is known as "call by name" where it passes an expression instead of an evaluated expression. This is very specific to Scala and not well supported with Mockito.
There is a host of workarounds to this:
Is there a way to match on a call-by-name argument of a Mockito mock object in Specs?
How to mock a method with functional arguments in Scala?
How do you mock scala call-by name in Mockito
The one by Eric looks the simplest and what you may want.

Related

How to mock scala generic method

I have a traits(below simple versions) and I want to mock Foo.
trait MyTrait[A]
trait Foo {
def bar[T: MyTrait](id:Int, data: T, other:Option[String] = None): String
}
I tried:
implicit val myTrait = new MyTrait[String] {}
val src = mock[Foo]
when(src.bar(any(),any(),any())).thenReturn("ok")
src.bar(1, "some", None)
It fails with:
Invalid use of argument matchers! 4 matchers expected, 3 recorded
How to mock this kind of method?
Mockito does not play well with scala code. What happens in your case is that
notify.bar(any(), any(), any()) has to be invoked inside when(), but type of the bar method is unknown, so when scalac is looking-up implicits there are possibly several instances of Writes that fit here (becuase all of them do).
You can do something like this to make it work:
when(src.bar[T](any(),any(),any())).thenReturn("ok")
Edit
Following your edit, i think you should reconsider usage of mockito in the first place. Here's what happens:
Foo has the following signature after desugaring
trait Foo {
def bar[T](id:Int, data: T, other:Option[String] = None)(implicit ev: MyTrait[T]): String
}
I don't know if you are aware how does mockito work, but here is a quick explanation why (from what i can tell) this error happens:
at runtime method bar has the following "signature" (due to type erasure):
bar(id: Int, data: Object, other: Option[Object], ev: MyTrait[Object])
when(src.bar[T](any(),any(),any())).thenReturn("ok") actually invokes this method on a proxy object and registers "matchers", but ev is passed myTrait instead of a matcher, so i guess this violates some constraints of the library
As side-note: usually mocking is not that hard and you can simply implement a "mocked" trait without any help from mockito or other similar library.
The syntax [T : MyTrait] is sugar to add (implicit typeClass: MyTrait[T]) as a second set of arguments, so basically you're missing an argument matcher as the error states
So if you do
val src = mock[Foo]
when(src.bar(any(),any(),any())(any())).thenReturn("ok")
it works as expected
BTW, this is a bit of self promotion but I just published a library called mockito-scala that improves the mockito syntax for Scala, is part of the mockito ecosystem so hopefully should become the default when working with Scala, you can find it here https://github.com/mockito/mockito-scala with the information to get the dependency and what problems does it actually solves.

How to Provide Specialized Implementations of Generic Methods in Scala?

I'm working on an existing code base with a wrapper class around Slick 2.1.0 (I know). This wrapper has a method named transaction that is a generic - it takes a (f: => T) (so it's pass-by-name). I need to mock this class for an unit test. We're also using Mockito 1.10.19 (again, I know), which won't let me mock a pass-by-name (I believe...). So I'm stuck implementing the underlying trait that this wrapper class is built on.
The immediate problem is this: I want to mock this transaction method so it does nothing. The code I'm testing passes in a (f: => Unit). So I want to implement this method to return a Future.Done. (Did I mention we're using Finagle and not Scala futures?) But this method is generic. How do I properly specialize?
This is my current attempt:
val mockDBM = new DatabaseManager {
override def transaction[#specialized(Unit) T](f: => T): Future[T] = Future.value(f)
def transaction(f: => Unit): Future[Unit] = Future.Done
}
Of course, I get a have same type after erasure error upon compilation. Obviously I have no idea how #specialized works.
What do I do? Maybe I can use Mockito after all? Or I need to learn what specializing a generic method actually means?
I found this, which probably contains the answer, but I have no formal background in FP, and I don't grok this at all: How can one provide manually specialized implementations with Scala specialization?
#specialized doesn't let you provide specializations, it just generates its own. The answer provided in the linked question would require changing the signature. From the question it looks like you can't change it, in which case you are out of luck. If you can... you may still be out of luck, depending on how exactly this code is going to be called.
OTOH, the solution for "I want to disregard f, but can only return Future.Done if the generic is for a Unit type" is far simpler:
class Default[A] {
var x: A = _
}
object Default {
def apply[A]() = (new Default[A]).x
}
val mockDBM = new DatabaseManager {
override def transaction[T](f: => T): Future[T] = {
Future.value(Default(x))
}
}
Assuming you need a successful future, but don't care about value, that is; if you just need any future, override def transaction[T](f: => T): Future[T] = Future.???.

Scala - how to create a single implicit that can be used for a type constructor

I'm trying to write a method which uses the isEmpty method on types String, Option and List. These classes don't share a common base trait with that method, so I've tried to pass an implicit EmptyChecker in with them:
trait EmptyChecker[Field] {
def isEmpty(data: Field): Boolean
}
implicit val StringEmptyChecker: EmptyChecker[String] = new EmptyChecker[String] {
def isEmpty(string: String): Boolean = string.isEmpty
}
def printEmptiness[Field](field: Field)(implicit emptyChecker: EmptyChecker[Field]): Unit = {
if (emptyChecker.isEmpty(field))
println("Empty")
else
println("Not empty")
}
printEmptiness("abc") // Works fine
The String empty checker works fine, but I've hit problems with making empty checkers for type constructors like Option and List.
For example, Option doesn't work:
implicit val OptionChecker: EmptyChecker[Option[_]] = new EmptyChecker[Option[_]] {
def isEmpty(option: Option[_]): Boolean = option.isEmpty
}
// Both fail compilation: "could not find implicit value for parameter emptyChecker: EmptyChecker[Some[Int]]
printEmptiness(Some(3))
printEmptiness[Option[Int]](Some(3))
If I use a specific Option[Int] checker, it works a little better, but is a bit ugly:
implicit val OptionIntChecker: EmptyChecker[Option[Int]] = new EmptyChecker[Option[Int]] {
def isEmpty(optionInt: Option[Int]): Boolean = optionInt.isEmpty
}
// Fails like above:
printEmptiness(Some(3))
// Passes compilation:
printEmptiness[Option[Int]](Some(3))
So my question is: is it possible to make a single EmptyChecker for each Option and List type and have them work with my method without needing to explicitly declare the type whenever I call it? I'm trying to get a type safe duck typing effect.
I'm using scala 2.11.6.
Thanks in advance!
The source of your problem is that the type of Some(1) is Some[Int], not Option[Int]. There are a couple of ways around this; you can explicitly upcast the expression with a type ascription: printEmptiness(Some(3): Option[Int]). Alternatively, you can define a helper method to do this for you automatically, and if you're using Scalaz, there's one of these provided:
import scalaz.syntax.std.option._
printEmptiness(3.some)
Furthermore if you do use Scalaz, you may find looking at the PlusEmpty/ApplicativePlus/MonadPlus type classes useful.

How to test type conformance of higher-kinded types in Scala

I am trying to test whether two "containers" use the same higher-kinded type. Look at the following code:
import scala.reflect.runtime.universe._
class Funct[A[_],B]
class Foo[A : TypeTag](x: A) {
def test[B[_]](implicit wt: WeakTypeTag[B[_]]) =
println(typeOf[A] <:< weakTypeOf[Funct[B,_]])
def print[B[_]](implicit wt: WeakTypeTag[B[_]]) = {
println(typeOf[A])
println(weakTypeOf[B[_]])
}
}
val x = new Foo(new Funct[Option,Int])
x.test[Option]
x.print[Option]
The output is:
false
Test.Funct[Option,Int]
scala.Option[_]
However, I expect the conformance test to succeed. What am I doing wrong? How can I test for higher-kinded types?
Clarification
In my case, the values I am testing (the x: A in the example) come in a List[c.Expr[Any]] in a Macro. So any solution relying on static resolution (as the one I have given), will not solve my problem.
It's the mixup between underscores used in type parameter definitions and elsewhere. The underscore in TypeTag[B[_]] means an existential type, hence you get a tag not for B, but for an existential wrapper over it, which is pretty much useless without manual postprocessing.
Consequently typeOf[Funct[B, _]] that needs a tag for raw B can't make use of the tag for the wrapper and gets upset. By getting upset I mean it refuses to splice the tag in scope and fails with a compilation error. If you use weakTypeOf instead, then that one will succeed, but it will generate stubs for everything it couldn't splice, making the result useless for subtyping checks.
Looks like in this case we really hit the limits of Scala in the sense that there's no way for us to refer to raw B in WeakTypeTag[B], because we don't have kind polymorphism in Scala. Hopefully something like DOT will save us from this inconvenience, but in the meanwhile you can use this workaround (it's not pretty, but I haven't been able to come up with a simpler approach).
import scala.reflect.runtime.universe._
object Test extends App {
class Foo[B[_], T]
// NOTE: ideally we'd be able to write this, but since it's not valid Scala
// we have to work around by using an existential type
// def test[B[_]](implicit tt: WeakTypeTag[B]) = weakTypeOf[Foo[B, _]]
def test[B[_]](implicit tt: WeakTypeTag[B[_]]) = {
val ExistentialType(_, TypeRef(pre, sym, _)) = tt.tpe
// attempt #1: just compose the type manually
// but what do we put there instead of question marks?!
// appliedType(typeOf[Foo], List(TypeRef(pre, sym, Nil), ???))
// attempt #2: reify a template and then manually replace the stubs
val template = typeOf[Foo[Hack, _]]
val result = template.substituteSymbols(List(typeOf[Hack[_]].typeSymbol), List(sym))
println(result)
}
test[Option]
}
// has to be top-level, otherwise the substituion magic won't work
class Hack[T]
An astute reader will notice that I used WeakTypeTag in the signature of foo, even though I should be able to use TypeTag. After all, we call foo on an Option which is a well-behaved type, in the sense that it doesn't involve unresolved type parameters or local classes that pose problems for TypeTags. Unfortunately, it's not that simple because of https://issues.scala-lang.org/browse/SI-7686, so we're forced to use a weak tag even though we shouldn't need to.
The following is an answer that works for the example I have given (and might help others), but does not apply to my (non-simplified) case.
Stealing from #pedrofurla's hint, and using type-classes:
trait ConfTest[A,B] {
def conform: Boolean
}
trait LowPrioConfTest {
implicit def ctF[A,B] = new ConfTest[A,B] { val conform = false }
}
object ConfTest extends LowPrioConfTest {
implicit def ctT[A,B](implicit ev: A <:< B) =
new ConfTest[A,B] { val conform = true }
}
And add this to Foo:
def imp[B[_]](implicit ct: ConfTest[A,Funct[B,_]]) =
println(ct.conform)
Now:
x.imp[Option] // --> true
x.imp[List] // --> false

Transforming Scala varargs into Java Object... varargs

I have a Java class that logs stuff which has a method like this:
void info(Object message, Object... params);
In Scala, I've created a wrapper around such call that looks like this:
def info(msg: => String, params: Any*) {
log.info(msg, params);
}
When I call:
val host = "127.0.0.1"
val port = "1234"
info("Start on {0}:{1}", host, port)
I get:
"Started on WrappedArray(127.0.0.1, 1234):{1}"
Now, does anyone now how to convert params into an Object[] that can be consumed properly?
I tried to do:
def info(msg: => String, params: Any*)
log.info(msg, params.toList.toArray);
}
But that doesn't work:
"Started on [Ljava.lang.Object;#14a18d:{1}"
Similar thing happens when you do:
params.asInstanceOf[WrappedArray[Object]].array
Found the answer:
log.info(msg, params.map(_.asInstanceOf[AnyRef]) : _*)
The following returns a Seq[AnyRef] => params.map(_.asInstanceOf[AnyRef]), and the ': _*' part tells the compiler to pass it as varargs
Result:
"Started on 127.0.0.1:1234"
Besides, this solution deals with both AnyVals and AnyRefs
#Galder - there is an easier way which allows you to avoid the cumbersome asInstanceOf[Object] call:
def info(msg: => String, params: Any*) = log.info( msg.format(params : _*) );
In scala 2.7, the format(args : Any*) function is implicitly included via RichString (and has a sub-optimal implementation is terms of reflection for no good reason that I can see) whereas in 2.8 the method is included via StringLike and is implemented via a direct call to String.format(String, Object ...)
I understand that the reason why Java does not contain such a method is that it has an implication that "every String is a format String", which is not the case. happily, I'm willing to forgo the logical correctness for the more useable class which scala provides!