Mockito versus Spock

In this recipe, we will write a simple test using Spock that verifies the behavior of the system under test when an exception is thrown. Before going into details, it's worth mentioning that Spock is a Groovy-based (http://groovy.codehaus.org/) tool. Therefore, in order to use it, you need to know at least the basics of the Groovy language. Spock is based on JUnit and is much more than a mocking framework. It gives you a beautiful BDD (Behavior Driven Development) syntax that will convert your tests to Specifications (capital S since Specification is a class that you need to extend to work with Spock).

If you want to try out Spock without installing it on your machine, check out the Spock Web Console at http://meetspock.appspot.com/, where you can write your tests online!

Spock is a perfect tool for you if you want to introduce Groovy into your project. You can start off with writing tests and then gradually progress towards production code (if that is what you want, of course). Spock's beautiful BDD approach, combined with the power of Groovy, makes it a perfect addition to your codebase.

Getting ready

To start working with Spock, you need to add it to your classpath. Remember that you also need to have Groovy attached. The following is the Groovy and Spock configuration for Gradle:

apply plugin: 'groovy'
compile "org.codehaus.groovy:groovy-all:2.3.1"
testCompile "org.spockframework:spock-core:0.7-groovy-2.0"

The following is how you can add Groovy and Spock to your classpath using Maven (please see the Mockito Cookbook Github repo at https://github.com/marcingrzejszczak/mockito-cookbook for the exact setup for both Gradle and Maven):

<project>
<build>
    <plugins>
      <plugin>
        <groupId>org.codehaus.gmaven</groupId>
        <artifactId>gmaven-plugin</artifactId>
        <version>1.5</version>
        <executions>
          <execution>
            <goals>
              <goal>testCompile</goal>
            </goals>
          </execution>
        </executions>
        <dependencies>
          <dependency>
            <groupId>org.codehaus.gmaven.runtime</groupId>
            <artifactId>gmaven-runtime-api</artifactId>
            <version>1.5</version>
            <exclusions>
              <exclusion>
                <groupId>org.codehaus.groovy</groupId>
                <artifactId>groovy-all-minimal</artifactId>
              </exclusion>
            </exclusions>
          </dependency>
          <dependency>
            <groupId>org.codehaus.groovy</groupId>
            <artifactId>groovy-all</artifactId>
            <version>2.3.1</version>
          </dependency>
        </dependencies>
      </plugin>
    </plugins>
  </build> 
  <dependencies>
    <dependency>
      <groupId>org.spockframework</groupId>
      <artifactId>spock-core</artifactId>
      <version>0.7-groovy-2.0</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>    

As in previous recipes, the system under test will be the tax transferring system for a given person, as shown in the following code:

public class TaxTransferer {

  private final TaxService taxService;

  public TaxTransferer(TaxService taxService) {
    this.taxService = taxService;
  }

  public boolean transferTaxFor(Person person) {
    if (taxService.hasAlreadyTransferredTax(person)) {
      return false;
    }    
    try {
      taxService.transferTaxFor(person);
    } catch (Exception exception) {
      System.out.printf("Exception [%s] caught while trying to transfer tax for [%s]%n", exception, person.getName());
      return false;
    }
    return true;
  }

}

How to do it...

To test the system using Spock, you need to perform the following steps:

  1. Make your test class extend the Specification class.
  2. Stub the mock's behavior through the static Stub() or Mock() method. If you want to verify the mock's behavior, then use Mock(). If you wish to only stub the execution, then use Stub().
  3. Execute the logic of the system under test.
  4. Verify the behavior of the system under test using the multiply operator (*) and the count of wanted executions.

The following snippet shows an example of a test with Spock (Spock as a dependency requires JUnit, and it's using a JUnit runner):

class TaxTransferrerSpec extends Specification {

    TaxService taxService = Mock()

    TaxTransferer systemUnderTest = new TaxTransferer(taxService);

    def 'should return false when tax was not transfered and connection to irs was refused'() {
        given:
            Person person = new Person()
        when:
            boolean transferSuccessful = systemUnderTest.transferTaxFor(person)
        then:
            !transferSuccessful
            1 * taxService.hasAlreadyTransferredTax(person) >> false
            1 * taxService.transferTaxFor(person) >> { throw new RuntimeException("Connection refused") }

    }

    @Unroll
    def "should return [#transferSuccessful] when tax wasn't already transferred and connection to irs was refused [#throwsException]"() {
        given:
            Person person = new Person()
        when:
            boolean transferSuccessfulResult = systemUnderTest.transferTaxFor(person)
        then:
            transferSuccessfulResult == transferSuccessful
            1 * taxService.hasAlreadyTransferredTax(person) >> false
            1 * taxService.transferTaxFor(person) >> { if(throwsException) { throw new RuntimeException("Connection refused") } }
        where:
            throwsException || transferSuccessful
            true            || false
            false           || true

    }

}

Note

Remember that Spock is a Groovy tool and the test code is written in Groovy. That's why the syntax differs from Java-based tests.

How it works...

We will not discuss how Spock works internally, but focus on what happens in the test itself, and what Spock's approach is.

Spock forces its users to follow the BDD approach (with the given, when, then, expect, and where clauses), thus the tests become very clear and automatically separated into sections. As for the stubbing strategy, Spock has separate methods for stubbing and mocking. This is also to show explicitly the difference between the two. What is more, it's a Groovy framework (already a main testing framework for Grails), so you can profit from all of the Groovy magic, which should make your tests become really clean.

Let's take a look at the second Spock test that shows how easily you can define parameterized tests. The @Unroll annotation makes Spock insert values that are named according to the columns in the where table, for each row of the where part. In fact, throughout the test, you can refer to those values by the names of the columns. The >> operator (right-shift operator) allows you to stub values with the result of the closure (the function defined within the curly braces). As you can see, we can even provide some more complex answers (like in the case of the transferTaxFor(…) method stubbing). The 1 * notation means that you want to verify that there was a single method execution.

There's more...

Mockito's test code of the system would look like the following (example for JUnit):

@RunWith(MockitoJUnitRunner.class)
public class TaxTransfererTest {

    @Mock TaxService taxService;

    @InjectMocks TaxTransferer systemUnderTest;

    @Test
    public void should_return_false_when_tax_was_not_transfered_and_connection_to_irs_was_refused() {
        // given
        Person person = new Person();
	    given(taxService.hasAlreadyTransferredTax(person)).willReturn(false);
        willThrow(new TaxServiceConnectionException("Connection refused")).given(taxService).transferTaxFor(person);

        // when
        boolean transferSuccessful = systemUnderTest.transferTaxFor(person);

        // then
        then(transferSuccessful).isFalse();
        verify(taxService).hasAlreadyTransferredTax(person);
        verify(taxService).transferTaxFor(person);
    }

}

The primary similarities between Mockito and Spock are as follows:

  • Similar BDD approach as in Mockito (for example, the methods from BDDMockito)
  • When used properly, both can produce very clear and readable code
  • You can use Hamcrest matchers in either of the frameworks

The primary differences between Mockito and Spock are as follows:

  • Spock forces you to use BDD, whereas in Mockito it's optional.
  • Spock is a Groovy-based tool, whereas Mockito is Java based.
  • Since Spock operates on Groovy when stubbing, you provide the desired behavior in closures (refer to http://groovy.codehaus.org/Closures for more information). You don't need any additional methods, which is contrary to Mockito.
  • You need to extend a Specification class to use Spock, whereas in Mockito you can use it straight away.
  • If you want to both stub a method and verify it, in Spock, you need to do that in the verification phase (in the then or expect block), which is really unintuitive.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.16.139.8