Grigor Avagyan is an Information Technologies Engineer. He has 12 years of experience in automation engineering, QA and development. Grigor's expertise includes manual and automated testing, continuous integration and Atlassian products.

Learn JMeter in 5 Hours

Start Learning
Slack

Run massively scalable performance tests on web, mobile, and APIs

Jan 25 2018

Spock vs. JUnit - Which One Should You Choose?

Spock and JUnit are both great testing frameworks for Java, and can be used for API testing. Personally, as an information technologies engineer, I prefer using Spock, and not only because it supports Groovy. In my opinion, Spock is easier and nicer to use. Inspired by JUnit, jMock, RSpec, Groovy, Scala and Vulcans, it enjoys a combined set of advantages. JUnit, on the other hand, is a very mature framework, and a very large audience enjoys its abilities.

 

In this blog post I will compare Spock and JUnit according to four parameters:

 

  • Parameterization
  • Mocking
  • Documenting tests and code
  • Verification

 

Let’s get started.

 

1. Parameterization

 

Parameterization is the technique of changing test data for the same test method, thus making the test run the same code but for changing data. We will often need to use parameterization in our test cases. Let’s look at a simple example that shows why.

 

Imagine we have a method that gets the filename as input and validates its extension. The requirement is that only jpeg, jpg and bmp extensions pass, while tiff and png extensions are not allowed at all. This method will return ‘true’ or ‘false’ based on the file extension. As we can see, the code for checking each file extension should be the same, except for the extension itself. Parameterization will make the code the most efficient and easy to work with.

 

Let’s see how parameterization works in Spock and in JUnit:

 

Spock (19 lines - empty lines not counted):

 

import spock.lang.Specification
import spock.lang.Unroll

@Title("Testing file extension validation method")
class ImageValidatorShould extends Specification {
  
   @Unroll
   def "validate extension of #fileToValidate"() {
       when: "validator checks filename"
       def isValid = validate fileToValidate

       then: "return appropriate result"
       isValid == expectedResult

       where: "input files are"
       fileToValidate || expectedResult
       'some.jpeg'    || true
       'some.jpg'     || true
       'some.tiff'    || false
       'some.bmp'     || true
       'some.png'     || false
   }
}

 

JUnit (30 lines - empty lines not counted):

 

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

import java.util.Collection;

import static java.util.Arrays.asList;
import static org.junit.Assert.assertEquals;

@RunWith(Parameterized.class)
public class ImageValidator {

   @Parameters
   public static Collection<Object[]> data() {
       return asList(new Object[][]{
               {"some.jpeg", true},
               {"some.jpg", true},
               {"some.tiff", false},
               {"some.bmp", true},
               {"some.png", false}
       });
   }

   private String file;
   private boolean isValid;

   public ImageValidator(String input, boolean expected) {
       file = input;
       isValid = expected;
   }

   @Test
   public void validateFileExtension() {
       assertEquals(isValid, validate(file));
   }
}

 

As we can see from the code snippets, the JUnit code is more than 50% longer. In addition, it is readable for Java developers, but for all others Spock is much more readable and clean.

 

Personally, as a Java engineer, when I saw Spock first time I had a feeling that it was not clean and understandable. But I gave it some time and experimented with it, and now all my tests are only in Spock.

 

Now let’s take a look at the execution output for these code snippets:

 

Spock:

 

spock vs. junit comparison

 

JUnit:

 

spock and junit comparison

 

Here, as we can see from execution times, JUnit is winning as it is much faster. But, Spock is nicer and the output provides more information about the extensions.

 

2. Mocking

 

Mocking is the technique of creating objects in the code that aren’t real, but they simulate the behaviour of real objects instead. Mocking is used to isolate the behaviour of a certain object, by using mocks for all the other objects except the one being tested. Please note that mocks aren’t Stubs. Read more about Mocking and the difference between Mocking and Stubbing from Martin Fowler’s web page.

 

For mocking (as well as stubbing) in Java (and more or less in all languages), you need to include a 3rd party library like EasyMock or Mockito. In Spock though, you do not need anything from a 3rd party. Spock itself is enough with its Mock().

 

Mocking (as well as Stubbing) in Spock is as easy as the following code:

 

def subscriber = Mock(Subscriber)
def receiver = Stub(Receiver)

 

In JUnit though, you need to do a bit more for Mocking (and Stubbing):

 

  • Choose a 3rd party library
  • Annotate the variable or field with @Mock
  • Initialise the mocks

 

@Mock
private Subscriber subscriber;

@Before
public void setup() {
	subscriber = new Subscriber()
}

 

Another important thing to mention is mock injection. Mock Injection is the act of putting Mocks into Mocked classes.

 

In JUnit (through a 3rd party library) you need to make sure to initialise Mocks or annotate your class with @RunWith(MockitoJUnitRunner.class).

 

In Spock though, you do not need to do this, because in Spock you have direct access to non-existing constructors, private fields and more. As result you can work even with Object references instead of Mocks. Let me show this in the following code snippets:

 

Java class:

 

public class Formatter() {
	private String message;
	private int count;
}

 

Spock:

 

class FormatterShould extends Specification {

   def "get and set fields"() {
       given: "formatter"
       def formatter = new Formatter()

       when: "setting a message"
       formatter.message = 'message'

       then: "setted message is correct"
       assert formatter.message == 'message'
   }
}

 

JUnit (only possible when you have public accessors or a public constructor that has access to private fields):

 

public class Formatter() {
	private String message;
	private int count;

      public Formatter(String message, int count) {
          this.message = message;
          this.count = count;
      }
}

 

This is a simple example where Spock accessed private class fields, which shows how powerful Spock is.

 

3. Documenting Tests and Code

 

In every piece of developed code, it is good practice to have self explaining methods, variable names and class names, objects, etc., especially when we need to work on legacy code. The same applies to test methods/classes, even more than for regular code, because regular code passes lots of quality gates and tests. So let’s see the differences between Spock and JUnit in this field.

 

In Spock, the code snippet documents our code by default. We have the @Title explanation for the whole test class, then in every test method we have given/when/then/{where} blocks and they all have explanations. Also, we have the test method name written in the simple and understandable English.

 

On the other hand, JUnit is losing on all levels, because there is no documentation “forced” by default. So if you want it, you have to develop brilliant self explanatory code yourself (let’s be fair here, in the legacy code this is almost impossible) and at least some comments should be added.

 

4. Verification

 

In JUnit, to assure a method was executed based on some condition(s), you have to have 3rd party dependencies, e.g. Mockito.

 

verify(someMockedClass).someMethod(isA(Some.class));

 

Exactly the same login in Spock will look like this:

 

1 * someMockedClass.someMethod

 

Note that for doing this in Spock you do not need 3rd party libraries.

 

The then() of Mockito used in JUnit (and other frameworks) looks like this:

 

when(someClass.someMethod(TEST)).thenReturn(result);

 

Yet in Spock you will have much less code and readability

 

someClass.someMethod(TEST) >> result

 

In other words, Spock uses 0* and >>, while JUnit uses verify() and then() .

 

Conclusion

 

As we can see, Spock has more readability and a clearer documented code, it does not need 3rd parties, and it is more powerful than JUnit. In the end, using Spock or JUnit or TestNG or anything else is absolutely up to you. They each have their pros and cons for sure.

 

One thing I can say though, it’s that in the past I used JUnit and TestNG. But when I heard about and experimented with Spock, I switched to it completely. If you switch to Spock from any other tool you might struggle in the beginning, but pretty quickly you will enjoy a clean and maintainable tool with documented test code. 

 

To try out API testing with BlazeMeter, just put your URL and assertion in the box below and your test will start in minutes. You can also request a demo.

 

Click here to subscribe to our newsletter.

Interested in writing for our Blog?Send us a pitch!

Your email is required to complete the test. If you proceed, your test will be aborted.