I think I get Spock Mocks now

I’ve been misunderstanding a fundamental issue of Spock Mocks. That’s annoying, but probably inevitable given that I work with so many state-of-the-art, evolving API’s. If you spend enough time on the bleeding edge, sooner or later you’ll get cut.

The problem is, though, I’ve been telling people something wrong for some time now, and that’s not acceptable. Thus this blog post. It’s one thing for me to make a mistake, but it’s quite another for me to mislead others. I want to fix that now. Besides, if I made the mistake, it’s also possible others are missing it, too.

I’m a big fan of the Spock testing framework. It’s very easy to learn, it works with both Java and Groovy systems, and it’s got a great mocking framework built into it. I’ve been a JUnit user for years, but I’ve never been able to commit to a mocking framework in Java. That’s partly because I still don’t find them particularly intuitive, and partly because I’m still not sure which one is going to win. I don’t want to commit to a framework (EasyMock? Mockito? PowerMock? etc) only to have to switch to a different one in a couple of years.

Spock is fun, though, and I use it whenever I can, and not just for the Star Trek related puns, some of which I’ll have to adopt here. Back in June, I wrote an article for NFJS the Magazine, entitled “Spock: I have been, and always shall be, your friendly testing framework.” I’m going to use an example from that article, with some variations, to show what I recently learned.

A basic Spock test

Here is part of a Groovy class called Tribble that answers the question, “Do you know what you get when you feed a tribble too much?”:

[sourcecode language=”groovy”]
class Tribble {
def feed() {
def tribbles = [this]
10.times { tribbles << new Tribble() }
return tribbles
}
}
[/sourcecode]

The answer, of course, is a whole bunch of hungry little tribbles. The feed method creates an ArrayList of tribbles by starting with the current instance and then adding 10 more. I know the return keyword isn’t strictly necessary, since closures automatically return their last evaluated value, but I use it sometimes for clear documentation. Groovy isn’t about writing the shortest code — it’s about writing the simplest, easiest to understand code that gets the job done.

To test this method, here’s a Spock test. It extends the spock.lang.Specification class (which is required) and ends in the word “Spec” (which isn’t, but makes for a nice convention):

[sourcecode language=”groovy”]
import spock.lang.Specification

class TribbleSpec extends Specification {
Tribble tribble = new Tribble()

def "feed a tribble, get more tribbles"() {
when:
def result = tribble.feed()

then:
result.size() == 11
result.each {
it instanceof Tribble
}
}
}
[/sourcecode]

I never thought JUnit was verbose until I met Spock. For those who haven’t used it much, first let me say you have something fun to look forward to. That said, let me explain the test. Spock tests have a def return type, then have a test name that describes what you’re trying to accomplish. The name is usually a short phrase, but it can be spread over several lines and even contain punctuation.

(Hamlet D’Arcy gives a great example in his blog post on Spock mocks, which is also echoed in the cool Spock Web Console. I also agree with him that Spock mocks should be called “smocks”, but since it doesn’t have a direct Star Trek association I’m not sure that will catch on.)

As Peter Niederweiser, the creator of the framework, points out, the method name becomes the body of an annotation, but that’s all under the hood.

The rest of the test consists of a when and a then block, representing a stimulus/response pair. The when block contains the method invocation, and the then block includes a series of boolean conditions that must be true for the test to pass. Nice and simple.

Tribbles do more than just eat, though. They react to others.

Like Dr. McCoy, I can mock Vulcans

Let me add a pair of methods to my Tribble class:

[sourcecode language=”groovy”]
String react(Klingon klingon) {
klingon.annoy()
"wheep! wheep!"
}

String react(Vulcan vulcan) {
vulcan.soothe()
"purr, purr"
}
[/sourcecode]

The overloaded react method is based on a pair of interfaces. Here’s the Vulcan interface:

[sourcecode language=”groovy”]
interface Vulcan {
def soothe()
def decideIfLogical()
}
[/sourcecode]

Here’s the Klingon interface:

[sourcecode language=”groovy”]
interface Klingon {
def annoy()
def fight()
def howlAtDeath()
}
[/sourcecode]

(Yeah, I know howling at death is a Next Generation thing, but go with it.)

Since both Vulcan and Klingon are interfaces, a mocking framework can generate an implementation with just Java’s basic dynamic proxy capabilities, which means I don’t need CGLIB in my classpath. To test the react method that takes a Vulcan, here’s the Spock mocking feature in action:

[sourcecode language=”groovy”]
def "reacts well to Vulcans"() {
Vulcan spock = Mock()

when:
String reaction = tribble.react(spock)

then:
reaction == "purr, purr"
1*spock.soothe()
}
[/sourcecode]

Spock provides the Mock method to create a mock implementation of the interface. When I then invoke the react method, I check that it returns the proper String and (here’s the cool part), I verify that the soothe method in the mock is invoked exactly once.

So far, so good. Klingons react rather badly to tribbles, however, so I thought it would funny if I had them throw an exception. Here’s my original test for the react method that takes a Klingon (warning: this doesn’t do what it looks like it does!):

[sourcecode language=”groovy”]
def "reacts badly to Klingons"() {
Klingon koloth = Mock()
koloth.annoy() >> { throw new Exception() }

when:
String reaction = tribble.react(koloth)

then:
0*koloth.howlAtDeath()
1*koloth.annoy()
reaction == "wheep! wheep!"
notThrown(Exception)
}
[/sourcecode]

Using the right-shift operator, my intention was to set the expectation that invoking the annoy method on a Klingon resulted in an exception. The plan was:

  • In the setup block (above when), declare that the annoy method throws an exception,
  • In the then block, verify that the method got called.

The problem is, what happens to the exception? Spock has two great methods for exception handling, called thrown and notThrown. I was able to verify that the method got called, but why did notThrown(Exception) return true? I even got back the string I expected. What’s wrong?

The right way to mock a Klingon

(from a galaxy far, far away, right?)

Here’s the problem: according to the Spock wiki page on Interactions, interactions defined outside a then block (here declaring that react throws an exception) are called global, while those defined inside a then block are called local, and local overrides global. Also, interactions without a cardinality are optional, while those with a cardinality are required.

In other words, I may have declared that react throws an exception, but in the then block I then changed it to say it actually doesn’t. In the then block, I say that react must be called once and doesn’t return anything. Therefore, no exception is thrown and the return value is as expected.

To achieve what I was actually after, here’s the right way to mock my Klingon:

[sourcecode langauge=”groovy”]
def "reacts badly to Klingons"() {
Klingon koloth = Mock()
1 * koloth.annoy() >> { throw new Exception() }
0 * koloth.howlAtDeath()

when:
String reaction = tribble.react(koloth)

then:
reaction == null
thrown(Exception)
}
[/sourcecode]

Now I set both the cardinality and the behavior outside the then block. The then block verifies both that the exception was thrown, and it checks the cardinality, too. Oh, and while I was at it, I verified that the howlAtDeath method didn’t get called. I doubt the Klingons howled at death when they burned down all the tribbles that Scotty beamed into their engine room just before they went to warp.

Admittedly, I still find the syntax a bit confusing, but at least I get it now. Hopefully you’ll get it, too, and they’ll be nah tribble at all.

(The source code for this example and the others used in my NFJS the Magazine article are in my GitHub repository, https://github.com/kousen/Spock-NFJS-Article . Eventually they will make their way into my book, Making Java Groovy, available now through the Manning Early Access Program.)

8 responses to “I think I get Spock Mocks now”

  1. You can also put both interactions into the then-block. That’s where I usually put required interactions (because they describe an expected outcome). Into the setup-block I mostly put interactions with objects that act as pure stubs (i.e. I just want them to return something and am not interested in verifying anything about them). This is just a convention though, and it’s up to you whether you put an interaction into a setup- or then-block. The behavior is the same except that interactions in a then-block have higher precedence and can thus override other interactions (e.g. from a setup() method).

    What happens internally is that interactions in a then-block are moved to right before the corresponding when-block by Spock’s AST transform. This is necessary because Spock’s mocking framework (like most Java mocking frameworks but unlike Mockito) needs to know about all expected interactions beforehand. This also explains why you have to give Spock a little hint if you factor out an interaction from a then-block into a separate method (see Specification#interaction). Without this hint, Spock wouldn’t know that it has to move the code.

  2. What I find confusing is that you move code from the then (check if the test ran ok) block to the test (setup and run the test) block. You either do different tests now, and no longer test if methods are called once or never, or I’m declaring a state of severe confusion.

  3. What’s changed is the point in time when the interaction is declared, not the point in time when it’s verified. In the vast majority of cases, this won’t affect the outcome of the test. If you don’t want any magic to happen, declare all interactions up-front.

  4. […] to be aware that interactions in the then: part have precedence over mocks written elsewhere. See this post for an in-depth discussion. I think Spock hasn’t figured out the best way to do it. At the […]

  5. Thank You…i found you post very useful

  6. Thanks for posting. This was extremely helpful from a number of angles.

  7. […] Das Spock-Framework verfügt auch über ein eigenes Framework für die Erstellung von Mocks. Die dort gebotenen Funktionen habe ich noch nicht ausprobiert, die Syntax ist jedoch einfach und sollte für die meisten Fälle ausreichend sein. Ein detailliertes Beispiel habe ich auf dieser Seite gefunden. […]

  8. Just wanted to thank you for this blog post. That mock behavior was driving me mad!

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Discover more from Stuff I've learned recently...

Subscribe now to keep reading and get access to the full archive.

Continue reading