Specs2 Mockito - Invoke Injected Callback

Mockito and Specs2 work great together and make testing my code a lot of fun. I ran into a problem yesterday in which I needed to get access to a callback function that was passed into an object that I was mocking. For some concreteness, I was mocking a zookeeper client and needed to invoke the callback function I passed to "zookeeper.watchNode(path, callbackFunction)".

Up until this point, I've only needed to verify arguments from my test. I haven't needed to actually do something with the argument itself. My original approach was to use a custom matcher to capture the parameter using function matchers. But that involved a var and was rather messy.

It turns out there is a MUCH better way to do this. Called "argument capture." In my case, my code looked like this:

      // The signature of the zookeeper watch function
      val listener = capture[(Option[Array[Byte]]) => Unit]

      // create system under test, which will call watchNode internally
      new SUT(zkMock)

      // Use the arg capturers to capture the params SUT passed in
      there was one(zkMock).watchNode(path, listener)

      // Now, call the callback method
      listener.value(Some("some updated value from zookeeper"))

      SUT.someValue must_== "some updated value"

Comments

Adam Rosien said…
Typically you put the capture into the stubbing call, but like you show you can also do it in the verification (there was one...).

Recent posts