Customizing test setup
Last updated
Last updated
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.
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.
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
and a custom base class: src/test/java/com/example/SomeClassDiffblueBase.java
then Cover will write a test class src/test/java/com/example/SomeClassDiffblueTest.java
extending that custom base class.
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 MethodsThe 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:
@AfterXXX
Annotated MethodsA 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:
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
and a custom base class: src/test/java/com/example/SomeClassDiffblueBase.java
Cover will use that initialized field to write the test class: src/test/java/com/example/SomeClassDiffblueTest.java