Java Programming Tutorials

Java programming tutorials with many code examples!

Spock Framework Mock and Closures

Problem:

Spock Framework Mock‘s are very easy to use. When mixed with Groovy closures they become very flexible too. Learn how to mix both!

Solution:

In post Spock Framework Mock we’ve created basic Java classes as our domain model and a controller that we want to test. There you could also see how to define simple interactions with Spock Framework Mocks.

Now we’ll extend that with the following test:

// an interface with two methods: exists(user), add(user)
def userService = Mock(UserService)

// a controller to test, that will use mock of the service:
def userController = new UserController(userService: userService)

def 'should add a new user'() {
    given:
    // The first call to "exists" will return "false",
    // all subsequent calls will return "true":
    userService.exists(_ as User) >>> [false, true]

    when:
    userController.addUser('Jon Snow')

    then:
    1 * userService.add(_ as User) >> {
        // This way we've got access to params in a closure:
        User user ->
        // Asserts are implicit only in "then" and "expect" blocks
        // so here we have to use it explicitly:
        assert user.name == 'Jon Snow'
    }

    when:
    userController.addUser('Ramsay Snow')

    then:
    0 * userService.add(_ as User)
}

Important things to note:

  1. when-then blocks can occur many times in Spock test – not only once.
  2. The expression >>> [items] means that each call to Mock‘s method will return subsequent item from the list, and the last one will be returned indefinitely.
  3. >> {…} in the first then-block means that closure (anonymous, executable block of code in braces) will be executed on the call to the Mock‘s method. It can return a value, which is not needed here.
  4. In closures assert must be explicitly stated.

Next time we’re going to play with exceptions in Spock Framework tests.

Share with the World!
  • UATP

    In the test method example above, in both “when” sections you refer to restController…
    restController.addUser(…)
    Shouldn’t that be userController?

    • The name of variable doesn’t really matter here, but I’ve changed it to match the controller and be more readable. Thanks!