DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

SBOMs are essential to circumventing software supply chain attacks, and they provide visibility into various software components.

Related

  • Cypress API Testing: A Detailed Guide
  • Fluent Assertions Reloaded
  • A Beginner’s Guide to Playwright: End-to-End Testing Made Easy
  • Automating E2E Tests With MFA: Streamline Your Testing Workflow

Trending

  • Multiple Stakeholder Management in Software Engineering
  • One Checkbox to Cloud: Migrating from Tosca DEX Agents to E2G
  • Event Storming Workshops: A Closer Look at Different Approaches
  • Reducing Hallucinations Using Prompt Engineering and RAG
  1. DZone
  2. Testing, Deployment, and Maintenance
  3. Testing, Tools, and Frameworks
  4. Testing Your API Assertions With the Spock Framework

Testing Your API Assertions With the Spock Framework

Learn how to test your APIs with Spock, a comprehensive testing framework that uses Java and Groovy, leveraging the benefits of several existing Java frameworks.

By 
Grigor Avagyan user avatar
Grigor Avagyan
·
Nov. 30, 17 · Tutorial
Likes (5)
Comment
Save
Tweet
Share
13.4K Views

Join the DZone community and get the full member experience.

Join For Free

Spock is a testing framework that uses the Java and Groovy programming languages. It's a comprehensive testing framework, covering everything you need for unit testing, BDD, and Mocks. Of course, you can test your APIs with Spock.

Created in 2008 by Peter Niederwieser from Gradle, who was later joined by Luke Daley (also from Gradle), the first release of Spock was in 2015. Since then, it has been used as the default test framework in Grails, as well as being used internally by Gradle, Groovy, MongoDB, Tapestry, Netflix, and more.

Spock leverages the benefits of existing Java frameworks: JUnit, TestNG, JBehave, Cucumber, Mockito, JMock, and EasyMock. Spock's main strength is that it has only one dependency. Therefore, users don't need different dependencies for each of these tools. Instead, they have one for Spock.

In addition, the LOC (lines of code) produced by Spock are much shorter, which makes Spock tests much more readable and maintainable.

Let's look at an example. Given we have a Java class that check files extensions:

public class FileExtensionValidator() {
  public boolean isValidExtension(Srting fileName) {
     ...
  }
}


The body of the method is not important for us, so for saving space I exchanged it with "...".

Now, let's cover this class with a Spock test.

@Unroll("Checking file name #pictureFile")
def "All kinds of JPEG file are accepted"() {
   given: "an file extension checker" 
   FileExtensionValidator validator = new FileExtensionValidator()
 
   expect: "that all jpeg filenames are accepted regardless of case" 

   validator.isValidExtension(pictureFile)    

   where: "sample image names are"   
   pictureFile << GroovyCollections.combinations([["sample.","Sample.","SAMPLE."],['j', 'J'], ['p', 'P'],['e','E',''],['g','G']])*.join()


This Spock class is 10 LOC and results in 72 test scenarios. Want to try doing the same in JUnit? Go ahead, but if you work with JUnit, you know that the same test would be much longer, roughly up to 3 times more!

Another big pro for Spock is that it uses the JUnit runner. This means that if you've already been running your tests with it, you can keep doing so, and you don't need to learn how to use a new runner! In addition, this makes your tests compatible with all existing JUnit tools.

Last but not least, Spock is written in Java and has a Groovy front-end (same as Gradle). This means that most of Java's functionalities can be used as is, in Spock and Groovy tests or projects.

However, to use Spock you have to learn a new language, Groovy. That being said, Groovy is an easy to learn language. Also, it's possible to use Java-like code for the first times you work with Groovy, until you become more professional at it.

Now let's look at how you can test your API assertions with Spock.

1. Add the required dependencies to our build.gradle file:

In the plugins section - 

apply plugin: 'groovy'


In the dependencies section -

compile group: 'org.codehaus.groovy.modules.http-builder', name: 'http-builder', version: '0.7.1'
testCompile group: 'org.spockframework', name: 'spock-core', version: '1.1-groovy-2.4'
testCompile group: 'org.spockframework', name: 'spock-spring', version: '1.1-groovy-2.4'


That's it! Spock is now enabled for our project. If you are using IntelliJ IDEA you will see that you now have two newly generated Groovy folders, in "main" and "test" (see picture):

2. Put your test Groovy class in the src/test/groovy folder on GitHub and name it ArrivalControllerTest. As you can guess, it will test the ArrivalController java class.

Let's take a look at what we have inside that test class:

import com.demo.BlazeMeterApi
import groovyx.net.http.RESTClient
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.test.context.ActiveProfiles
import org.springframework.test.context.ContextConfiguration
import spock.lang.Specification

import static com.demo.constant.Paths.ARRIVAL
import static com.demo.constant.Paths.VERSION
import static io.restassured.http.ContentType.JSON

@SpringBootTest(
       classes = BlazeMeterApi.class,
       webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT
)
@ActiveProfiles(value = "test")
@ContextConfiguration
class ArrivalControllerTest extends Specification {

   RESTClient restClient = new RESTClient("http://localhost:16666", JSON)

   def "Check Arrivals controller"() {
       restClient.auth.basic 'blaze', 'Q1w2e3r4'

       when: "get all arrivals"
       def response = restClient.get(
               path: VERSION + ARRIVAL + 'all',
               requestContentType: JSON
       )

       then: "Status is 200"
       response.status == 200

       and: "Body contains proper values"
       assert response.data[0].id == 1
       assert response.data[0].city == 'Buenos Aires'
       assert response.data.size == 7
   }
}


Now let's understand what is going on inside this test.

@SpringBootTest(
       classes = BlazeMeterApi.class,
       webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT
)
@ActiveProfiles(value = "test")
@ContextConfiguration

This part of the code is responsible for:

  • Ramping up a Spring Context with a defined port and the main class BlazeMeterApi.class
  • Making sure this file will work only on test profiles

RESTClient restClient = new RESTClient("http://localhost:16666", JSON)

This is a simple REST client for interacting with API endpoints.

def "Check Arrivals controller"() {
       restClient.auth.basic 'blaze', 'Q1w2e3r4'

       when: "get all arrivals"
       def response = restClient.get(
               path: VERSION + ARRIVAL + 'all',
               requestContentType: JSON
       )

       then: "Status is 200"
       response.status == 200

       and: "Body contains proper values"
       assert response.data[0].id == 1
       assert response.data[0].city == 'Buenos Aires'
       assert response.data.size == 7
   }

This part is the actual test. In this test scenario we are calling the VERSION + ARRIVAL + 'all' endpoint, and then asserting the status and part of the response body as a JSON with items.

  • The method  def "Check Arrivals controller"()  is a fully qualified String message. This will be visible in execution and make it easier to find out what is going on in the test, step by step.
  • When - BDD Gherkin language. In this part of test we are calling the API endpoint.
  • Then/And - BDD Gherkin language. This is the part that performs the assertions. In this case: assert response.data[0].id == 1 and assert response.data[0].city == 'Buenos Aires'.

Please note that there are no assertions like in JUnit; rather, there is only one assert that will make sure the equation is valid.

4. Finally, let's look at the execution results when everything is going well. On the left side, you can see the name that we used in the Spock test as a method name.

Now, let's look at a case when the test fails, so we can see the power of Spock assert.

So I changed the id to 2, added a whitespace in the Buenos Aires and changed 7 to 8. After the execution, I got this error message:

Condition not satisfied:

response.data[0].id == 2
|        |   |   |  |
|        |   |   1  false
|        |   [id:1, city:Buenos Aires]
|        [[id:1, city:Buenos Aires], [id:2, city:Rome], [id:3, city:London], [id:4, city:Berlin], [id:5, city:New York], [id:6, city:Dublin], [id:7, city:Cario]]
groovyx.net.http.HttpResponseDecorator@943cf5

Expected :2
Actual   :1

As you can see, in other cases you would only have a message that the Assertion failed. However, Spock provides you with everything you need to debug and fix the test, even without debugging the test/application itself. We can immediately see that the id of the item with index 0 cannot be 2 because Spock provided us with the list of items as proof.

This is very important, because if you are working in big enterprise projects, you know that ramping up an environment is sometimes very expensive, and even though the test and fix only require 5-10 minutes, the whole process will take hours.

Spock (testing framework) API Testing Assertion (software development) Framework Groovy (programming language) intellij

Published at DZone with permission of , DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Cypress API Testing: A Detailed Guide
  • Fluent Assertions Reloaded
  • A Beginner’s Guide to Playwright: End-to-End Testing Made Easy
  • Automating E2E Tests With MFA: Streamline Your Testing Workflow

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • [email protected]

Let's be friends: