LogoLogo
diffblue.comFree trial
  • Discover Diffblue Cover
  • Get Started
    • What is Diffblue Cover?
    • Get started
      • Free trial
      • Get started - Cover Plugin
      • Get started - Cover CLI
      • Get started - Cover Pipeline
      • Get started - Cover Reports
    • Specs & Reqs
    • Reference Deployments
    • Licensing
      • Online license activation
      • Offline license activation
      • Diffblue License Manager
    • Update Cover
    • FAQs
    • Diffblue Learning
      • Get started
        • Just the basics
        • Free trial
        • Cover Plugin (IDE)
        • Cover CLI (Command Line)
      • Developer
        • Unit tests (IDE)
        • Unit tests (CLI)
        • Test coverage
      • DevOps
        • GitHub
        • GitLab
        • Other CI
      • Administrator
        • Admin - IntelliJ
        • Admin - CLI
        • Admin - Reports
      • Test coverage
        • Developer
        • Senior developer
        • Cover Reports Administrator
  • EVALUATION & ONBOARDING
    • Proof of Value
    • Jumpstart
      • Prerequisites for onboarding
      • Phase 1: Up and running
        • Module 1: Create your Cover unit test baseline
        • Module 2: Cover Pipeline CI integration
      • Phase 2: Developer productivity
        • Module 3: Getting started using Cover
        • Module 4: Introduction to Cover Reports
      • Phase 3: Advanced topics
        • Module 5: Speed up your test execution
        • Module 6: Getting more from Cover
  • Features
    • Cover Plugin
      • Writing tests
        • Gutter icons
        • Menu options
        • Run configurations
        • Cover Plugin tool window
        • Test Review
        • Test examples
        • Creating partial tests
        • Creating skeleton tests
        • Covering all enum values
        • Test insertion order
        • Diffblue Sandbox
        • Environment Check Cache
      • Project configuration
        • General dependencies
        • Test framework dependencies
      • Cover Plugin settings
        • Test Naming
        • Test Formatting
        • Spring configuration options
        • Method Annotations
        • Test Directory
        • Reset Cover Plugin settings
      • Cover Plugin admin
        • Core Maintenance
        • Cover Plugin toolbar menu
        • Cover Plugin status bar widget
        • Telemetry
        • Memory management
        • Using SonarQube with Cover Plugin
        • Log files
        • Troubleshooting
    • Cover CLI
      • Writing tests
        • Command summary
        • Test examples
        • Creating partial tests
        • Customizing test inputs
        • Customizing test setup
        • Test naming
        • Test formatting
        • Test insertion order
        • Patch files
        • Diffblue Sandbox
        • Operational behaviors
        • Test validation
      • Project configuration
        • Preflight checks
        • General dependencies
        • Test framework dependencies
        • Compiling your project successfully
          • Building a Maven project
          • Building a Gradle project
        • Configuring Cover to work with your project's build system
          • Quick guide
          • Configuration file in detail
          • Getting Started with Ant Projects
          • Default configuration
        • Mocking using Mockito
        • Spring profiles
        • Runtime environment
      • Commands & Arguments
        • Environment configuration for CI
        • Packages, classes, and methods
        • Quoting command line arguments
        • Argument files
      • Cover CLI admin
        • Core Maintenance
        • Telemetry
        • Memory management
        • Using Cover CLI in Eclipse
        • Using SonarQube with Cover CLI
        • Log files
        • Troubleshooting
      • Environment Configuration
    • Cover Pipeline
      • Cover Pipeline for CI
        • Quick Start - General
        • Quick Start - Jenkins
        • Quick Start - Azure Pipelines
        • Quick Start - AWS Codebuild
        • Integrating Diffblue Cover into CI on pull requests
        • Installation - VMs or CI run
      • Cover Pipeline for GitLab
        • Introduction
        • Installation and initial setup
        • GitLab workflow
        • Configuration
        • Troubleshooting
        • Related topics
      • Cover Pipeline for GitHub
        • Introduction
        • Installation and initial setup
        • GitHub workflow
        • Configuration
        • Troubleshooting
        • Related topics
    • Cover Reports
      • Cover Reports Contributor
        • Java project config (JaCoCo)
        • Generate and upload reports bundles
        • Authenticated uploads
      • Cover Reports User
        • Navigation
        • Dashboards
        • Telemetry data
        • Export API
        • Considerations
      • Cover Reports Administrator
        • Install and update Cover Reports
        • Configuration options
        • Database backup
        • SSO with Cover Reports
        • Uninstall Cover Reports
    • Cover Optimize
      • Get started - Cover Optimize
      • Cover Optimize & Gradle
      • Cover Optimize & Maven
      • Patch files
    • Cover Refactor
      • Get started - Cover Refactor
    • Cover Annotations
      • Mocking Annotations
      • Custom Input Annotations
      • Interesting Value Annotations
    • Output Codes
      • E - Environment Codes
      • L - License Codes
      • R - Reason Codes
      • T - Testability Codes
      • V - Validation Codes
      • Working with output codes
        • Working with code E020
        • Working with codes E057 to E065
        • Working with code E085
        • Working with code R005
        • Working with code R006
        • Working with code R008
        • Working with code R011
        • Working with code R012
        • Working with code R013
        • Working with code R026
        • Working with code R031
        • Working with code V003
    • Tutorials
      • How to measure test quality
      • How to improve code coverage
      • How to test a new feature
      • How to find regressions
      • How to use Diffblue Cover in test driven development (TDD)
      • How to write tests for Kotlin projects
      • Examples of tests created by Diffblue Cover
      • Best practices for testing private methods
  • Updates & Upgrades
    • Update Cover
    • Cover Editions
    • What's new
    • Release archive
      • 2025-05-01
      • 2025-04-02
      • 2025-04-01
      • 2025-03-02
      • 2025-03-01
      • 2025-02-02
      • 2025-02-01
      • 2025-01-02
      • 2025-01-01
      • 2024-12-02
      • 2024-12-01
      • 2024-11-02
      • 2024-11-01
      • 2024-10-02
      • 2024-10-01
      • 2024-09-02
      • 2024-09-01
      • 2024-08-02
      • 2024-08-01
      • 2024-07-04
      • 2024-07-03
      • 2024-07-01
      • 2024-06-02
      • 2024-06-01
      • 2024-05-02
      • 2024-05-01
      • 2024-04-02
      • 2024-04-01
      • 2024-03-02
      • 2024-03-01
      • 2024-02-02
      • 2024-02-01
      • 2024-01-02
      • 2024-01-01
      • 2023-12-02
      • 2023-12-01
      • 2023-11-03
      • 2023-11-02
      • 2023-11-01
      • 2023-10-02
      • 2023-10-01
      • 2023-09-02
      • 2023-09-01
      • 2023-08-02
      • 2023-08-01
      • 2023-07-03
      • 2023-07-02
      • 2023-07-01
      • 2023-06-02
      • 2023-06-01
      • 2023-05-02
      • 2023-05-01
      • 2023-04-02
      • 2023-04-01
      • 2023-03-02
      • 2023-03-01
      • 2023-02-02
      • 2023-02-01
      • 2023-01-02
      • 2023-01-01
      • 2022-12-02
      • 2022-12-01
      • 2022-11-02
      • 2022-11-01
      • 2022-10-03
      • 2022-10-02
      • 2022-10-01
      • 2022-09-02
      • 2022-09-01
      • 2022-08-05
      • 2022-08-03
      • 2022-08-02
      • 2022-08-01
      • 2022-07-02
      • 2022-07-01
      • 2022-06-02
      • 2022-06-01
      • 2022-05-02
      • 2022-05-01
      • 2022-04-02
      • 2022-04-01
      • 2022-03-02
      • 2022-03-01
      • 2022-02-02
      • 2022-02-01
      • 2022-01-02
      • 2022-01-01
      • 2021-06-02
      • 2021-02-01
  • Legal
    • Diffblue Legal
      • Diffblue End User License Agreement (EULA)
      • Cover Third Party Notices and/or Licenses
      • Privacy Notice
Powered by GitBook
On this page
  • Background
  • eLearning
  • Custom Base Class
  • @BeforeXXX Annotated Methods
  • @AfterXXX Annotated Methods
  • Field Inputs

Was this helpful?

Export as PDF
  1. Features
  2. Cover CLI
  3. Writing tests

Customizing test setup

PreviousCustomizing test inputsNextTest naming

Last updated 1 year ago

Was this helpful?

By default, Diffblue Cover will write tests that are executed in isolation but it's possible to provide a custom base class with additional logic to run before / after the tests themselves.

Background

A key feature of Diffblue Cover is automatically configuring classes such that the method under test can be successfully executed.

However, sometimes Diffblue Cover is unable to appropriately configure and clean up the environment such that tests can be usefully written and needs guidance from the user in the form of a custom base class which can provide behavior inherited by the test class.

eLearning

Custom Base Class

When writing tests for com.example.SomeClass Diffblue Cover will look for the existence of com.example.SomeClassDiffblueBase and use that as a super-class when writing com.example.SomeClassDiffblueTest. This com.example.SomeClassDiffblueBase class can contain methods to be run before/after writing tests, correctly annotated according to the testing framework used. The base class needs to have the same name as the class under test, with a DiffblueBase suffix appended, it must be in the same package as the class under test, but likely should be defined in the src/test/java source tree so that it’s kept separate from production code.

Note that if you're creating tests with TestNG for a class that uses Spring, the custom base class feature cannot be used.

Given a class under test: src/main/java/com/example/SomeClass.java

package com.example;

class SomeClass {
  void methodUnderTest() {
    // ...
  }
}

and a custom base class: src/test/java/com/example/SomeClassDiffblueBase.java

package com.example;

class SomeClassDiffblueBase {

}

then Cover will write a test class src/test/java/com/example/SomeClassDiffblueTest.java extending that custom base class.

package com.example;

import org.junit.Test;

class SomeClassDiffblueTest extends SomeClassDiffblueBase {
  @Test
  void testMethodUnderTest() {
    // Arrange
    // ...

    // Act
    // ...

    // Assert
    // ...
  }
}
package com.example;

import org.junit.jupiter.api.Test;

class SomeClassDiffblueTest extends SomeClassDiffblueBase {
  @Test
  void testMethodUnderTest() {
    // Arrange
    // ...

    // Act
    // ...

    // Assert
    // ...
  }
}
package com.example;

import org.testng.annotations.Test;

class SomeClassDiffblueTest extends SomeClassDiffblueBase {
  @Test
  void testMethodUnderTest() {
    // Arrange
    // ...

    // Act
    // ...

    // Assert
    // ...
  }
}

Note: Once the custom base class has been written or updated, please make sure that it has been compiled so that Cover is able to find the compiled class.

@BeforeXXX Annotated Methods

The most common use case for using a custom base class is to customize the test setup, often to perform some static initialization of some environmental state.

For example, your base class might need to switch to some test environment before tests are run at all, and might need to reset some license limits ahead of each test run.

If your class under test needs some shared environment state to be set up before tests are run at all, you can add a static, visible, no-argument method to your base class annotated with org.junit.jupiter.api.BeforeAll (or org.junit.BeforeClass if using JUnit 4, respectively org.testng.annotations.BeforeClass if using TestNG) performing that initialization logic.

If your methods under test need some state setup or reset before each test is run, you can add a non-static, visible, no-argument method to your base class annotated with org.junit.jupiter.api.BeforeEach (or org.junit.Before if using JUnit 4, respectively org.testng.annotations.BeforeMethod if using TestNG) performing that initialization logic.

For example, your base class might look like the following, with setupTestEnvironment() being called once before SomeClassDiffblueTest, and resetLicenseLimits() being called before each test method found:

package com.example;

import org.junit.BeforeClass;
import org.junit.Before;

class SomeClassDiffblueBase {

  @BeforeClass
  public static void setupTestEnvironment() {
    // custom static configuration
    Environment.state = new TestEnvironment();
  }

  @Before
  public void resetLicenseLimits() {
    // reset license limits
    Licensing.remainingUsages = 100;
  }
}
package com.example;

import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;

class SomeClassDiffblueBase {

  @BeforeAll
  static void setupTestEnvironment() {
    // custom static configuration
    Environment.state = new TestEnvironment();
  }

  @BeforeEach
  void resetLicenseLimits() {
    // reset license limits
    Licensing.remainingUsages = 100;
  }
}
package com.example;

import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;

class SomeClassDiffblueBase {

  @BeforeClass
  public void setupTestEnvironment() {
    // custom static configuration
    Environment.state = new TestEnvironment();
  }

  @BeforeMethod
  public void resetLicenseLimits() {
    // reset license limits
    Licensing.remainingUsages = 100;
  }
}

@AfterXXX Annotated Methods

A less common use case for a custom base class is to customize the test cleanup logic.

If your class under test needs some shared environment state to be cleared after tests are all run, you can add a static, visible, no-argument method to your base class annotated with org.junit.jupiter.api.AfterAll (or org.junit.AfterClass if using JUnit 4, respectively org.testng.annotations.AfterClass if using TestNG) performing that logic.

If your method under test needs some state reset after each test is run, you can add a non-static, visible, no-argument method to your base class annotated with org.junit.jupiter.api.AfterEach (or org.junit.After if using JUnit 4, respectively org.testng.annotations.AfterMethod if using TestNG) performing that logic.

For example, your base class might look like the following, with resetLicenseUsageCount() being called after each test in SomeClassDiffblueTest and then resetTestEnvironment() called after all the tests:

package com.example;

import org.junit.AfterClass;
import org.junit.After;

class SomeClassDiffblueBase {

  @AfterClass
  public static void resetTestEnvironment() {
    // clear test configuration
    Environment.state = null;
  }

  @After
  public void resetLicenseUsageCount() {
    // reset license limits
    Licensing.usageCount = 0;
  }
}
package com.example;

import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;

class SomeClassDiffblueBase {

  @AfterAll
  static void resetTestEnvironment() {
    // clear test configuration
    Environment.state = null;
  }

  @AfterEach
  void resetLicenseUsageCount() {
    // reset license limits
    Licensing.usageCount = 0;
  }
}
package com.example;

import org.testng.annotations.AfterClass;
import org.testng.annotations.AfterMethod;

class SomeClassDiffblueBase {

  @AfterClass
  public void resetTestEnvironment() {
    // clear test configuration
    Environment.state = null;
  }

  @AfterMethod
  public void resetLicenseUsageCount() {
    // reset license limits
    Licensing.usageCount = 0;
  }
}

Field Inputs

Another use case for custom base classes is to provide initialized inputs that Cover would otherwise struggle to get right.

For example, perhaps your method under test requires some ComplexObject in order to execute, but it requires multiple calls to configure.

Note: Currently only static fields can be used.

Given a class under test: src/main/java/com/example/SomeClass.java

package com.example;

class SomeClass {
  void methodUnderTest(ComplexObject complex) {
    // ...
  }
}

and a custom base class: src/test/java/com/example/SomeClassDiffblueBase.java

package com.example;

import org.junit.Before;

class SomeClassDiffblueBase {

  static ComplexObject complex;

  @Before
  public void resetTestEnvironment() {
    complex = ComplexObject.builder()
      .withName("For Unit Tests")
      .withSquareNumber(64)
      .build();
  }
}
package com.example;

import org.junit.jupiter.api.BeforeEach;

class SomeClassDiffblueBase {

  static ComplexObject complex;

  @BeforeEach
  void resetTestEnvironment() {
    complex = ComplexObject.builder()
      .withName("For Unit Tests")
      .withSquareNumber(64)
      .build();
  }
}
package com.example;

import org.testng.annotations.BeforeMethod;

class SomeClassDiffblueBase {

  static ComplexObject complex;

  @BeforeMethod
  public void resetTestEnvironment() {
    complex = ComplexObject.builder()
      .withName("For Unit Tests")
      .withSquareNumber(64)
      .build();
  }
}

Cover will use that initialized field to write the test class: src/test/java/com/example/SomeClassDiffblueTest.java

package com.example;

import org.junit.Test;

class SomeClassDiffblueTest extends SomeClassDiffblueBase {

  @Test
  public void testMethodUnderTest() {
    // Arrange
    SomeClass someClass = new SomeClass();

    // Act
    someClass.methodUnderTest(SomeClassDiffblueBase.complex);

    // Assert
    // ...
  }
}
package com.example;

import org.junit.jupiter.api.Test;

class SomeClassDiffblueTest extends SomeClassDiffblueBase {

  @Test
  void testMethodUnderTest() {
    // Arrange
    SomeClass someClass = new SomeClass();

    // Act
    someClass.methodUnderTest(SomeClassDiffblueBase.complex);

    // Assert
    // ...
  }
}
package com.example;

import org.testng.annotations.Test;

class SomeClassDiffblueTest extends SomeClassDiffblueBase {

  @Test
  public void testMethodUnderTest() {
    // Arrange
    SomeClass someClass = new SomeClass();

    // Act
    someClass.methodUnderTest(SomeClassDiffblueBase.complex);

    // Assert
    // ...
  }
}