Skip to content

Yet another programming solutions log

Sample bits from programming for the future generations.

Technologies Technologies
  • Algorithms and Data Structures
  • Java Tutorials
  • JUnit Tutorial
  • MongoDB Tutorial
  • Quartz Scheduler Tutorial
  • Spock Framework Tutorial
  • Spring Framework
  • Bash Tutorial
  • Clojure Tutorial
  • Design Patterns
  • Developer’s Tools
  • Productivity
  • About
Expand Search Form

Spock Framework Mock

farenda 2015-06-20 2

Problem:

Spock Framework Mocks are powerful and very easy to use. Learn here how to use and interact with Mocks in your unit tests on these examples!

Solution:

Common scenario: test a class that interacts with other classes, but don’t instantiate half of the system just for a unit test. In our example we want to test UserController, which could be a REST controller for Users. It receives data from a GUI and delegates to a UserService to perform actual work with the data. We know that UserService implementations work and we only want to test the controller.

So… let’s start with definitions of Java classes used in tests: User, UserService interface, and UserController.

First our domain object used in tests, User:

package com.farenda.solved;

public class User {

    private final String name;

    public User(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    @Override
    public String toString() {
        return "User('" + name + "')";
    }
}

Now the UserService interface that we will mock in tests:

package com.farenda.solved;

import java.util.Set;

public interface UserService {

    /**
     * Return true when user exists.
     */
    boolean exists(User user);

    /**
     * Add a new user, but only if it doesn't exist yet.
     *
     * @param user to add
     */
    void add(User user);

    /**
     * Remove a user with given name.
     *
     * @param name of user to remove
     */
    void remove(String name);

    /**
     * Return all users.
     *
     * @return All users or empty Set.
     */
    Set<User> getAll();
}

Next, the REST Controller:

package com.farenda.solved;

public class UserController {

    private UserService userService;

    public void setUserService(UserService userService) {
        this.userService = userService;
    }

    public void addUser(String name) {
        userService.add(new User(name));
    }
}

We’ve got basic setup. Now it’s time to test the controller:

package com.farenda.solved

import spock.lang.Specification

class BasicMocksTest extends Specification {

    // Creating Mock is simple as that:
    def userService = Mock(UserService)

    // This will also work, but I prefer the former version:
    // def UserService anotherService = Mock()

    // In Groovy you can call setter like this:
    def restController = new UserController(userService: userService)

    def 'should not add existing users'() {
        given:
        // For any User passed as parameter return "true" from Mock
        // We don't specify how many times we expect it to be called,
        // because we don't care in this test:
        userService.exists(_ as User) >> true

        when:
        restController.addUser('Jon Snow')

        then:
        // "n * method()" means "expect _exactly_ n calls of method()"
        // Change 0 to some other value and see what is happens!
        0 * userService.add(_ as User)
    }
}

Things to note here:

  1. Spock Mocks work only with interfaces by default. If you want to mock classes be sure to have cglib and org.objenesis on the classpath (see posts on Spock Framework config for Gradle and Maven).
  2. In calls to Mock there is _ as Type, which means “any object of type Type”. If you would pass an object here (instantiated User) then it would be compared using equals with values passed as parameter.
  3. method() >> value means “on call to method() return value”.
  4. If you want you can specify how many times method may be called. It can be a number or a range:
    method()             // any number of times
    0 * method()         // expect 0 invocations
    (1..3) * method()    // expect 1 to 3 calls
    (_..2) * method()    // expect at most 2 calls
    (1.._) * method()    // expect at least 1 call
    

    Flexible, isn’t it? :-)

  5. Mock methods are defined in given and then blocks. They can be defined in any place, and it’s just a matter of style. I put definitions that direct flow of execution in given block and calls that are expected results in then/expect blocks. This way I state my intentions clearly.

OK. When you run the above test you’ll see that it… fails! :-)

Spock Framework Mock Too many invocations
Spock Framework Mock Too many invocations

It’s on purpose. In test I stated that user should not be added when already exists, but the implementation always calls userService.add() method. Let’s fix that:

public void addUser(String name) {
    User user = new User(name);
    if (!userService.exists(user)) {
        userService.add(user);
    }
}

Now it works as expected! :-)

You’ve learned basics of Mocking in Spock Framework! In subsequent posts we’ll show more complex and interesting examples leveraging power of Spock and Groovy.

Share with the World!
Categories Spock Framework Tags unit-tests
Previous: Bash while loop
Next: Spock Framework Mock and Closures

Recent Posts

  • Java 8 Date Time concepts
  • Maven dependency to local JAR
  • Caesar cipher in Java
  • Java casting trick
  • Java 8 flatMap practical example
  • Linked List – remove element
  • Linked List – insert element at position
  • Linked List add element at the end
  • Create Java Streams
  • Floyd Cycle detection in Java

Pages

  • About Farenda
  • Algorithms and Data Structures
  • Bash Tutorial
  • Bean Validation Tutorial
  • Clojure Tutorial
  • Design Patterns
  • Java 8 Streams and Lambda Expressions Tutorial
  • Java Basics Tutorial
  • Java Collections Tutorial
  • Java Concurrency Tutorial
  • Java IO Tutorial
  • Java Tutorials
  • Java Util Tutorial
  • Java XML Tutorial
  • JUnit Tutorial
  • MongoDB Tutorial
  • Quartz Scheduler Tutorial
  • Software Developer’s Tools
  • Spock Framework Tutorial
  • Spring Framework

Tags

algorithms bash bean-validation books clojure design-patterns embedmongo exercises git gof gradle groovy hateoas hsqldb i18n java java-basics java-collections java-concurrency java-io java-lang java-time java-util java-xml java8 java8-files junit linux lists log4j logging maven mongodb performance quartz refactoring regex rest slf4j solid spring spring-boot spring-core sql unit-tests

Yet another programming solutions log © 2022

sponsored