Using Spock to test JPA entities in a Spring Boot application

In my previous post we saw how to test JPA entities along with the Spring Data repository layer in a Spring Boot based application. We made use of JUnit and the AssertJ library.

In this post we will look at how to use the Spock framework to test the same. In fact, in this example, I will be using a combination of Spock based tests along with JUnit tests.To know more about the Spock framework, view the official site here. Spock is a testing and specification framework for Java and Groovy applications.

Let’s get started…

Setup using maven: ( pom.xml)  


<properties>
<spock.version>1.1-groovy-2.4</spock.version>
</properties>
<dependencies>
<dependency>
<groupId>org.spockframework</groupId>
<artifactId>spock-spring</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<compilerId>groovy-eclipse-compiler</compilerId>
<source>1.8</source>
<target>1.8</target>
</configuration>
<dependencies>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-eclipse-compiler</artifactId>
<version>2.9.2-01</version>
</dependency>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-eclipse-batch</artifactId>
<version>2.4.3-01</version>
</dependency>
</dependencies>
</plugin>
</plugins>

  1. We need to add the spock-spring dependency. This will bring in the dependencies required to run Spock based tests in a Spring boot based application.
  2. Notice the use of <spock.version>1.1-groovy-2.4</spock.version>. We are overriding the spock version. Spring Boot 1.5.4 brings in version 1.0 of Spock, however this needs a @ContextConfiguration to run Spock based tests in a Spring Boot application. Overriding the version to 1.1 removes the need to add this annotation.
  3. In the plugin section , we need to add the dependency for groovy-eclipse-compiler which will compile the groovy code. Spock is based on groovy and hence using Spock to write tests means we write groovy code.

Test classes using Spock

As mentioned in my earlier post, let us consider the same example of 2 JPA entities, SocialMediaSite and Users ( OneToMany). A User has an email which we represented as EmailAddress value object.  The test class for this looks as follows:

EmailAddressTest.groovy


package com.boot.test.db;
import com.boot.entity.EmailAddress;
import spock.lang.Specification
public class EmailAddressTest extends Specification {
private static final String testEmail = "test@test.com";
def "throw exception for invalid format of email address"(String emailAddress)
{
when:
"create invalid email address"
def email = new EmailAddress(emailAddress);
then:
"throw exception for invalid format of email address"
def e = thrown(IllegalArgumentException)
e.message == "Email Address is Invalid !"
where:
emailAddress | _
"test@.com" | _
" " | _
null | _
}
def "return valid email address"()
{
when:
"create new email address"
def email = new EmailAddress(testEmail);
then:
"return valid email"
email.toString() == testEmail;
}
}

  1. The test class extends spock.lang.Specification. This is how you begin writing a Spock based test.
  2. Notice the method names are strings, nice descriptive methods names.
  3. The when/then syntax is for assertions. It’s like saying, “Hey, when this happens then check these things”.
  4. The where section is the first test method above is data driven.Notice the first 2 columns, emailAddress and a blank. This is because data driven tables in Spock need 2 columns. We need just one. The next rows supply data to the same method.Hence this method is run with all the values mentioned in the first column starting from the 2nd row. Now that is awesome compared to writing multiple methods which do the same thing or if you are using TestNG, this is done using a DataProvider.
  5. Notice that we have not used any Assertion library here. In Spock this is done using ==.

SocialMediaSiteRepositoryTest.groovy


package com.boot.test.db;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import com.boot.entity.EmailAddress;
import com.boot.entity.SocialMediaSite;
import com.boot.entity.User;
import com.boot.repository.SocialMediaSiteRepository;
import spock.lang.Specification
@DataJpaTest
public class SocialMediaSiteRepositoryTest extends Specification{
@Autowired
private SocialMediaSiteRepository socialMediaSiteRepository;
def facebook = new SocialMediaSite("Facebook", "Online Social Media and Networking Service")
def "find social media site FaceBook by Id" () {
def savedFaceBookEntity = socialMediaSiteRepository.save(facebook)
when: "load facebook entity"
def faceBookEntityFromDb = socialMediaSiteRepository.findOne(savedFaceBookEntity.getId())
then:"saved and retrieved entity by id must be equal"
savedFaceBookEntity.getId() == faceBookEntityFromDb.getId()
}
def "find social media site facebook by name"() {
def savedFaceBookEntity = socialMediaSiteRepository.save(facebook)
when: "find by name FaceBook"
def socialMediaEntity = socialMediaSiteRepository.findByName("Facebook")
then: "saved and retrieved entity by name must be equal"
socialMediaEntity == savedFaceBookEntity
}
def "add users to social mediate site users " () {
setup:
def firstUser = new User("Mar", "Zuckerber", new EmailAddress("mark@mark.com"));
facebook.addUser(firstUser);
def savedFaceBookEntityWithUsers = socialMediaSiteRepository.save(facebook)
when:
def faceBookEntityFromDB = socialMediaSiteRepository.findOne(savedFaceBookEntityWithUsers.getId())
then:
faceBookEntityFromDB.getUsers() != null
faceBookEntityFromDB.getUsers().size() == 1;
}
}

Notice the @DataJpaTest annotation on the class. It  spawns an in-memory data base and runs our tests  against it. Along with this, the JPA entities are scanned, Transactions, Hibernate  and Spring Data are also configured. There is no need to add @ContextConfiguration as we are using Spock 1.1.

Running Spock tests and JUnit tests together

I have added the 2 groovy test files in src/test/groovy.  We can have tests written in JUnit too. I have a JUnit based test class in src/test/java. The groovy eclipse compiler dependency we added in the pom.xml compiles and run tests from both the packages.

Conclusion

This is my first experience with Spock framework and I have thoroughly enjoyed writing tests with it ! There is of course a lot more to the Spock framework. I hope you have enjoyed this quick introduction to Spock for testing Spring Data Repository and JPA entities in a Spring Boot application. The synergy between Spock and the testing changes made in Spring Boot since version 1.4 (test slices) is great !

You can find the project on github.

2 thoughts on “Using Spock to test JPA entities in a Spring Boot application”

    1. Which part of the code is giving you this NPE? Could you please post a stacktrace of the same? I just checked out the code (link posted on the article) and ran it, it worked without any issues.

      Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: