jqwik Spring Support
This project provides an extension to support testing of Spring and Spring-Boot applications with jqwik.
Table of Contents
How to Install
Gradle
Follow the
instructions here
and add the following dependency to your build.gradle
file:
dependencies {
implementation("org.springframework:spring-context:5.3.14")
...
testImplementation("net.jqwik:jqwik-spring:0.9.0")
testImplementation("org.springframework:spring-test:5.3.14")
}
You can look at a sample project using jqwik, Spring Boot and Gradle.
Maven
Follow the
instructions here
and add the following dependency to your pom.xml
file:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.14</version>
</dependency>
...
<dependency>
<groupId>net.jqwik</groupId>
<artifactId>jqwik-spring</artifactId>
<version>0.9.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.3.14</version>
<scope>test</scope>
</dependency>
Supported Spring Versions
You have to provide your own version of Spring or Spring Boot through Gradle or Maven. The jqwik-spring library has been tested with versions:
5.2.15-RELEASE
5.3.14
Please report any compatibility issues you stumble upon.
Supported JUnit Platform Versions
You need at least version 1.8.2
of the JUnit platform - otherwise
strange things could happen.
Keep in mind that if you are using Spring Boot you will have to
explicitly set the JUnit platform version.
Standard Usage
To enable autowiring of a Spring application context or beans you just have to
add @JqwikSpringSupport
to your test container class:
import net.jqwik.api.*;
import net.jqwik.api.constraints.*;
import net.jqwik.api.lifecycle.*;
import net.jqwik.spring.*;
import org.junit.jupiter.api.*;
import org.springframework.beans.factory.annotation.*;
import org.springframework.test.context.*;
@JqwikSpringSupport
@ContextConfiguration(classes = MySpringConfig.class)
class MySpringProperties {
@Autowired
private MySpringBean mySpringBean;
@Property
void nameIsAddedToHello(@ForAll @AlphaChars @StringLength(min = 1) String name) {
String greeting = mySpringBean.sayHello(name);
Assertions.assertTrue(greeting.contains(name));
}
}
Configuration and autowiring of values is delegated to Spring's own test framework. Therefore all integration testing annotations can be used. This is also true for standard annotation support.
Lifecycle
Spring will recreate its application context for each annotated class. That means, that
- Singleton beans will only be created once for all tests of one test container class.
- Properties and tries within the same class share mutual state of all Spring-controlled beans.
If you want a property to recreate the app context for each try, you have to annotate
the property method with
@DirtiesContext
.
Compare the following two properties:
@JqwikSpringSupport
@ContextConfiguration(classes = MySpringConfig.class)
class MySpringProperties {
@Property(tries = 10)
void counterIsCountingUp(@Autowired MyCounter counter) {
counter.inc();
// Prints out 1, 2, 3 ... 10
System.out.println(counter.value());
}
@Property(tries = 10)
@DirtiesContext
void counterIsAlways1(@Autowired MyCounter counter) {
counter.inc();
// Prints out 1, 1, 1 ... 1
System.out.println(counter.value());
}
}
Parameter Resolution of Autowired Beans
Autowired beans will be injected as parameters in example and property methods, in all lifecycle methods and also in the test container class's constructor - if there is only one:
@JqwikSpringSupport
@ContextConfiguration(classes = MySpringConfig.class)
class MyOtherSpringProperties {
@Autowired
MyOtherSpringProperties(MySpringBean springBean) {
Assertions.assertNotNull(springBean);
}
@BeforeProperty
void beforeProperty(@Autowired MySpringBean springBean) {
Assertions.assertNotNull(springBean);
}
@Property
void beanIsInjected(@Autowired MySpringBean springBean) {
Assertions.assertNotNull(springBean);
}
}
Spring JUnit Jupiter Testing Annotations
jqwik's Spring support is trying to mostly simulate how Spring's native Jupiter support works. Therefore, some of that stuff also works, but a few things do not.
Supported Jupiter Test Annotations
Spring Boot
By using @JqwikSpringSupport
as described above most - if not all - Spring Boot
testing features, e.g. test auto-configuration annotations should work.
This was tested with the following Spring Boot versions:
2.2.13.RELEASE
2.3.12.RELEASE
2.4.8
2.5.8
2.6.2
Please report any issues you have with other versions.
Shortcomings
Nested/Grouped Tests in Old Spring (Boot) Versions
Up to Spring version 5.2.15.RELEASE
, which comes with Spring Boot 2.3.12.RELEASE
,
the Spring extension and configuration is NOT handed down to inner test groups.
Also, member variables in the outer instance are not being auto wired
even if the inner class has all necessary annotations.
This is due to limitations of Spring's own testing framework
and cannot be fixed by this library.
Release Notes
0.9.0
- Upgrade jqwik 1.6.3
- Upgrade to JUnitPlatform 5.8.2
- Tested with Spring 5.3.14
- Tested with Spring Boot 2.6.2
0.8.2
- Upgrade jqwik 1.5.6
- Upgrade to JUnitPlatform 5.8.1
- Tested with Spring 5.3.11
- Tested with Spring Boot 2.5.5
0.8.1
- For Spring >= 5.3.0 test configuration is now "inherited" to
nested container classes annotated with
@Group
.
0.8.0
- Upgrade to jqwik 1.5.3
- Tested with more recent versions of Spring and Spring Boot