Skip to content
jqwik extension to support testing of Spring and Spring-Boot applications
Java
Branch: master
Clone or download

README.md

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.2.4.RELEASE")
    ...
    testImplementation("net.jqwik:jqwik-spring:0.5.0")
    testImplementation("org.springframework:spring-test:5.2.4.RELEASE")
}

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.2.4.RELEASE</version>
</dependency>
...
<dependency>
  <groupId>net.jqwik</groupId>
  <artifactId>jqwik-spring</artifactId>
  <version>0.5.0</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-test</artifactId>
  <version>5.2.4.RELEASE</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.0-RELEASE
  • 5.2.4-RELEASE

Please report any compatibility issues you stumble upon.

Supported JUnit Platform Versions

You need at least version 1.6.1 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 @AddLifecycleHook(JqwikSpringExtension.class) 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.*;

@AddLifecycleHook(JqwikSpringExtension.class)
@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:

@AddLifecycleHook(JqwikSpringExtension.class)
@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:

@AddLifecycleHook(JqwikSpringExtension.class)
@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);
    }
}

Annotations

There are two dedicated annotations to simplify set up of jqwik test container classes with Spring:

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

Unsupported Jupiter Test Annotations

  • @SpringJunitConfig: Replace with @net.jqwik.spring.SpringJqwikConfig

  • @SpringJunitWebConfig: Replace with @net.jqwik.spring.SpringJqwikWebConfig

  • @EnabledIf: Planned for future versions

  • @DisabledIf: Planned for future versions

Spring Boot

The current version has no dedicated support for Spring Boot but the usual stuff works out of the box.

Shortcomings

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.

You can’t perform that action at this time.