Define Unit Tests (Java)
You already have an existing Java Domain service, you want to include unit testing for that service.
Descriptionโ
This How-To guide will teach you how to:
- Add unit tests into your Java Domain Service service projects.
- Mock frequently used SDK dependencies in your implementation classes.
Please note that the links to the workbench tools in this tutorial only apply to the IBM Education Environment we provide. If you are using a different environment, e.g. your own installation, you will need to navigate directly to the required tools.
Test Phasesโ
In Java, a typical unit test can be broken down into several phases:
-
Setup: This is where you set up the necessary objects and data for the test using the @Before annotation in JUnit.
-
Execution: This is where you execute the code being tested by invoking a method or performing some other operation.
-
Verification: This is where you check the result of the execution to ensure that it matches the expected result using assertions.
-
Teardown: This is where you clean up any objects or resources created during the test using the @After annotation in JUnit.
Java Domain Service service project testing follows this pattern, where in each phase we do some necessary steps. The following are the steps to be done in each phase for Java Domain service project testing

Stepsโ
Add Test Dependencyโ
In your Java Domain Service service project, JUnit testing framework can be used to write unit tests. To include its dependency, add the following code into your ''pom.xml'' file
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
By including this dependency in your pom.xml file, you can take advantage of the many testing utilities and features provided by Spring Boot such as Mockito and Hamcrest.
In this How-To we will use Mockito as mocking framework, it allows you to create mock objects with a simple and intuitive API, and then define their behavior using a set of easy-to-use methods. You can then use these mock objects in your unit tests to simulate the behaviour of the real objects, and test your code in isolation.
Create Test Packages and Classesโ
Within your project structure, you need to create your test package and classes, This should correspond to your Java Domain Service implementation files strcuture having test packages for api, domain and integration namespaces, see below example

Ideally for each api provider, command, service and agent implementation file, you would create a corresponding test file.

Mocking Vs Injecting Dependenciesโ
In JUnit 5, the dependencies of a test class are the objects or instances it requires to perform its tests. These dependencies may consist of other classes, objects, or resources necessary for setting up the test environment, executing the tests, and validating the outcomes. To supply these dependencies, JUnit 5 provides two methods: Mocking and Injection.
Mocking Dependenciesโ
When designing a unit test, you should aim to test your code in isolation, meaning that you should only test the unit of code you are interested in, without its dependencies. Therefore, it is usually a good practice to mock dependencies instead of injecting real objects.
Mocking allows you to create objects that behave in a controlled and predictable way, and to verify that your code interacts with them correctly. This way, you can test your code without worrying about the behaviour of its dependencies.
Below is an example of testing a service and mocking dependneices.
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.BDDMockito;
public class MyServiceTestWithMocking {
private DomainEntityBuilder entityBuilder;
private Repository repo;
private MntsRepository mntsRepository;
private CallNotesRepo callNotesRepo;
private MyService myService;
@BeforeEach
public void setup() {
// Create needed mocks
entityBuilder = BDDMockito.mock(DomainEntityBuilder.class);
mntsRepository =BDDMockito.mock(MntsRepository.class);
callNotesRepo = BDDMockito.mock(CallNotesRepo.class);
repo = BDDMockito.mock(Repository.class);
// Create service instance with mocked entity builder and repository
myService = new MyService(entityBuilder, repo);
// Mocking Repository Calls
BDDMockito.when(repo.getMnts()).thenReturn(mntsRepository);
BDDMockito.when(mntsRepository.getCallNotes()).thenReturn(callNotesRepo);
}
@Test
public void testMyServiceExecute() {
// Create Input Entity
NotesEntity mockedRootEntity = new NotesEntity.NotesEntityBuilder()
.setNoteName("Test Name")
.setPriority("High")
.build();
// Set up the mock dependencies
BDDMockito.when(callNotesRepo.find(testData.getName())).thenReturn(mockedRootEntity);
// Call the service method
OutputEntity result = myService.execute(inputEntity);
// Verify the result
assertEquals(mockedRootEntity, result.getNotes());
}
}
Mocking is generally preferred for unit testing, the decision of whether to mock or inject real objects should be based on the specific requirements of your test and the constraints of your code.
Injecting Dependenciesโ
There are situations where you may want to Inject real objects instead of mocking them. For example, if your code logic relies on result from another service or command , you may need to inject real objects to test your code. In this case, you should still aim to isolate your code as much as possible, and only inject the minimum number of dependencies needed to test your code.
An example of testing a service and injecting dependneices via a MyServiceConfig.class. MyServiceConfig.class is a call hat you can create that helps you to specify the configuration for the Spring context.
@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = {MyServiceConfig.class})
public class MyServiceTestWithInjection {
@Autowired
private MyService myService;
@Test
public void testMyServiceExecute() {
// Create Input Entity
NotesEntity inputEntity = new NotesEntity.NotesEntityBuilder()
.setNoteName("Test Name")
.setPriority("High")
.build();
// Call the service method
OutputEntity result = myService.execute(inputEntity);
// Verify the result
assertNotNull(result);
assertEquals("Test Name", result.getName());
}
}
In above example, we use
- @ExtendWith annotation to load the Spring context with the SpringExtension class.
- @ContextConfiguration(classes = {MyServiceConfig.class}) specifies the configuration class for the Spring context that should be loaded for the test. This loads the necessary beans for MyService to be injected into the test class.
- @Autowired to inject an instance of MyService into the test class. Finally, we write a test case that calls a method on myService and verifies the result.
In above example, we are still loading the entire Spring context for the test. Depending on the complexity of your application and the number of beans you need to load, you may need to use a different approach to improve test performance.
Test Data Setupโ
As mentioned previously in Test Phases, within each test file, you would need to setup your test data and do necessary mocking. Below is an example
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.BDDMockito;
public class MyServiceTestWithDataSetup {
// Declare needed dependencies
private DomainEntityBuilder entityBuilder;
private Repository repo;
private MyService myService;
private CallNotesEntity callNotesEntity;
@BeforeEach
public void setup() {
// prepare service input entity
mockedCallNotesEntity = new CallNotesEntity.CallNotesBuilder()//
.setAgenda("Agenda")//
.setCallType(CallType.PHONE)//
.setContent("Content")//
.setEnd(OffsetDateTime.parse("2022-12-03T10:15:45+01:00"))//
.setStart(OffsetDateTime.parse("2022-12-03T10:15:30+01:00"))//
.setSubject("Subject")//
.setMeetingParticipant(new ArrayList<>())//
.build();
// Mocking needed dependneices and their nested dependneices
entityBuilder = BDDMockito.mock(DomainEntityBuilder.class);
repo = BDDMockito.mock(Repository.class);
// Mock some repository calls
MntsRepository mntsRepository = BDDMockito.mock(Repository.class);
CallNotesRepository callNotesRepo = BDDMockito.mock(CallNotesRepository.class);
BDDMockito.when(repo.getMnts()).thenReturn(mntsRepository);
BDDMockito.when(mntsRepository.getCallNotes()).thenReturn(callNotesRepo);
// Mock the `callNotesRepo` repo findAll call and return list with mocked root entity
BDDMockito.when(callNotesRepo.findAll()).thenReturn( List.of(mockedCallNotesEntity));
// Create service instance that you want to test its logic
myService = new MyService(entityBuilder, repo);
}
}
In the setup() method annotated with *@BeforeEach*, the test class sets up the required objects and dependencies for the test. It creates a mock implementation of the DomainEntityBuilder Class and a mock implementation of the Repository interface, which will be used by the MyService instance being tested.
It also creates a CallNotesEntity instance, which will be used as the input for the service method being tested.
Finally, the MyService instance being tested is created, using the mock implementations of DomainEntityBuilder and Repository.
Mock Repositoryโ
To be able to mock the Repository class in your implementation class (service, command, or agent), it's essential to understand its structure and hierarchy. The Repository class is a part of your service project SDK that groups all the repository facades for domain namespaces.
For instance, the following code is an example of a repository facade that groups two domain namespaces with prefixes (mnts and notes) repositories.
@Component
public class Repository {
protected de.k5.minutes.minutes.sdk.domain.mnts.facade.MntsRepository mnts;
protected de.k5.minutes.minutes.sdk.domain.notes.facade.NotesRepository notes;
public Repository(de.k5.minutes.minutes.sdk.domain.mnts.facade.MntsRepository mnts,
de.k5.minutes.minutes.sdk.domain.notes.facade.NotesRepository notes) {
this.mnts = mnts;
this.notes = notes;
}
public de.k5.minutes.minutes.sdk.domain.mnts.facade.MntsRepository getMnts() {
return mnts;
}
public void setMnts(de.k5.minutes.minutes.sdk.domain.mnts.facade.MntsRepository mnts) {
this.mnts = mnts;
}
public de.k5.minutes.minutes.sdk.domain.notes.facade.NotesRepository getNotes() {
return notes;
}
public void setNotes(de.k5.minutes.minutes.sdk.domain.notes.facade.NotesRepository notes) {
this.notes = notes;
}
}
Each domain namespace has a repository facade that consists of repositories for each root entity within the domain. For instance, MntsRepository contains two repositories for root entities callNotes and fileNote.
@Component
public class MntsRepository {
protected de.k5.minutes.minutes.sdk.domain.mnts.repository.CallNotesRepository callNotes;
protected de.k5.minutes.minutes.sdk.domain.mnts.repository.FileNoteRepository fileNote;
public MntsRepository(de.k5.minutes.minutes.sdk.domain.mnts.repository.CallNotesRepository callNotes,
de.k5.minutes.minutes.sdk.domain.mnts.repository.FileNoteRepository fileNote) {
this.callNotes = callNotes;
this.fileNote = fileNote;
}
public de.k5.minutes.minutes.sdk.domain.mnts.repository.CallNotesRepository getCallNotes() {
return callNotes;
}
public void setCallNotes(de.k5.minutes.minutes.sdk.domain.mnts.repository.CallNotesRepository callNotes) {
this.callNotes = callNotes;
}
public de.k5.minutes.minutes.sdk.domain.mnts.repository.FileNoteRepository getFileNote() {
return fileNote;
}
public void setFileNote(de.k5.minutes.minutes.sdk.domain.mnts.repository.FileNoteRepository fileNote) {
this.fileNote = fileNote;
}
}
To properly test a service that uses a repository, it's important to understand and mock the repository hierarchy. Depending on which repository you're using, the hierarchy may differ. Below is an example of how to test a service and mock the repository hierarchy.
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.BDDMockito;
public class MyServiceTestWithRepositoryMocking {
// Declare dependencies that will be mocked
private DomainEntityBuilder entityBuilder;
private Repository repo;
private MntsRepository mntsRepository;
private CallNotesRepo callNotesRepo;
private MyService myService;
@BeforeEach
public void setup() {
// 1. Mock Repository Facade
repo = BDDMockito.mock(Repository.class);
// 2. Mock Domain Namespace Repository
mntsRepository =BDDMockito.mock(MntsRepository.class);
// 3. Mock the root entity Repository that will be called within your logic
callNotesRepo = BDDMockito.mock(CallNotesRepo.class);
// Either Mock Repository Calls
BDDMockito.when(repo.getMnts()).thenReturn(mntsRepository);
BDDMockito.when(mntsRepository.getCallNotes()).thenReturn(callNotesRepo);
// Or use setters
repo.setMnts(mntsRepository);
mntsRepository.setCallNotes(callNotesRepo);
// Create Mocked root entity
CallNotesEntity mockedRootEntity = new CallNotesEntity.CallNotesEntityBuilder()
.setNoteName("Test Name")
.setPriority("High")
.build();
// 4. Mock the `callNotesRepo` repo find call and return mocked root entity
BDDMockito.when(callNotesRepo.find(testData.getName())).thenReturn(mockedRootEntity);
// Create service instance with mocked entity builder and repository
entityBuilder = BDDMockito.mock(DomainEntityBuilder.class);
myService = new MyService(entityBuilder, repo);
}
}
Mock Entity Builderโ
In your implementation class (service, command, or agent), you have access to DomainEntityBuilder class. To be able to mock DomainEntityBuilder, it's necessary to understand its structure and hierarchy.
The DomainEntityBuilder class is generated as a part of your service project SDK to group all the entity builder facades for domain namespaces.
Below is an example of a DomainEntityBuilder class that groups two domain namespaces entity builders with prefixes (mnts and notes).
@Component
public class DomainEntityBuilder {
protected de.k5.minutes.minutes.sdk.domain.mnts.facade.MntsEntityBuilder mnts;
protected de.k5.minutes.minutes.sdk.domain.notes.facade.NotesEntityBuilder notes;
public DomainEntityBuilder(de.k5.minutes.minutes.sdk.domain.mnts.facade.MntsEntityBuilder mnts,
de.k5.minutes.minutes.sdk.domain.notes.facade.NotesEntityBuilder notes ) {
this.mnts = mnts;
this.notes = notes;
}
public de.k5.minutes.minutes.sdk.domain.mnts.facade.MntsEntityBuilder getMnts() {
return mnts;
}
public void setMnts(de.k5.minutes.minutes.sdk.domain.mnts.facade.MntsEntityBuilder mnts) {
this.mnts = mnts;
}
public de.k5.minutes.minutes.sdk.domain.notes.facade.NotesEntityBuilder getNotes() {
return notes;
}
public void setNotes(de.k5.minutes.minutes.sdk.domain.notes.facade.NotesEntityBuilder notes) {
this.notes = notes;
}
}
Each builder facade for the domain namespaces includes a builder for each entity within its domain.
Below is an example of the MntsEntityBuilder, which contains two repositories for root entities.
@Component
public class MntsEntityBuilder {
public de.k5.minutes.minutes.sdk.domain.mnts.entity.CallNotesEntity.CallNotesBuilder getCallNotes() {
return new de.k5.minutes.minutes.sdk.domain.mnts.entity.CallNotesEntity.CallNotesBuilder();
}
public de.k5.minutes.minutes.sdk.domain.mnts.entity.CreateCallNoteInputEntity.CreateCallNoteInputBuilder getCreateCallNoteInput() {
return new de.k5.minutes.minutes.sdk.domain.mnts.entity.CreateCallNoteInputEntity.CreateCallNoteInputBuilder();
}
}
Depending on which entity builder you are using, you need to mock the hierarchy.
Below is an example of testing a service and mocking entity builder hierarchy.
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.BDDMockito;
public class MyServiceTestWithEntityBuilderMocking {
// Declare dependencies that will be mocked
private DomainEntityBuilder entityBuilder;
private Repository repo;
private MyService myService;
@BeforeEach
public void setup() {
// 1. Create Entity builder for `Mnts` domain namespace
MntsEntityBuilder mntsEntityBuilder = new MntsEntityBuilder();
// 2. Mock Domain Entity Builder Facade
entityBuilder = BDDMockito.mock(DomainEntityBuilder.class);
// 3. Either Mock DomainEntityBuilder Call to `getMnts()` and return mntsEntityBuilder instance
BDDMockito.when(entityBuilder.getMnts()).thenReturn(mntsEntityBuilder);
// Or use setters
entityBuilder.setMnts(mntsEntityBuilder);
// Create service instance with mocked entity builder and repository
repo = BDDMockito.mock(Repository.class);
myService = new MyService(entityBuilder, repo);
}
}
Mock Event Builderโ
In your implementation class that is configured to send events in its domain model (service, command, or agent), you have access to DomainEventBuilder class. To be able to mock DomainEventBuilder, it's necessary to understand its structure and hierarchy.
The DomainEventBuilder class is generated as a part of your service project SDK to group all the event builder facades for domain namespaces.
Below is an example of a DomainEventBuilder class that groups two domain namespaces event builders with prefixes (mnts and notes).
@Component
public class DomainEventBuilder {
protected de.k5.minutes.minutes.sdk.domain.mnts.facade.MntsEventBuilder mnts;
protected de.k5.minutes.minutes.sdk.domain.notes.facade.NotesEventBuilder notes;
public DomainEventBuilder(de.k5.minutes.minutes.sdk.domain.mnts.facade.MntsEventBuilder mnts,
de.k5.minutes.minutes.sdk.domain.notes.facade.NotesEventBuilder notes) {
this.mnts = mnts;
this.notes = notes;
}
public de.k5.minutes.minutes.sdk.domain.mnts.facade.MntsEventBuilder getMnts() {
return mnts;
}
public void setMnts(de.k5.minutes.minutes.sdk.domain.mnts.facade.MntsEventBuilder mnts) {
this.mnts = mnts;
}
public de.k5.minutes.minutes.sdk.domain.notes.facade.NotesEventBuilder getNotes() {
return notes;
}
public void setNotes(de.k5.minutes.minutes.sdk.domain.notes.facade.NotesEventBuilder notes) {
this.notes = notes;
}
}
Each builder facade for the domain namespaces includes a builder for each event within its domain.
Below is an example of the MntsEventBuilder, which contains event builder for MinutesLifecycleEvent.
@Component
public class MntsEventBuilder {
public MinutesLifecycleEventBuilder getMinutesLifecycleEvent(){
return new MinutesLifecycleEvent.MinutesLifecycleEventBuilder();
}
}
Depending on which entity builder you are using, you need to mock the hierarchy.
Below is an example of testing a service and mocking entity builder hierarchy.
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.BDDMockito;
public class MyServiceTestWithEntityBuilderMocking {
// Declare dependencies that will be mocked
private DomainEntityBuilder entityBuilder;
private Repository repo;
private MyService myService;
@BeforeEach
public void setup() {
// 1. Create Entity builder for `Mnts` domain namespace
MntsEntityBuilder mntsEntityBuilder = new MntsEntityBuilder();
// 2. Mock Domain Entity Builder Facade
entityBuilder = BDDMockito.mock(DomainEntityBuilder.class);
// 3. Either Mock DomainEntityBuilder Call to `getMnts()` and return mntsEntityBuilder instance
BDDMockito.when(entityBuilder.getMnts()).thenReturn(mntsEntityBuilder);
// Or use setters
entityBuilder.setMnts(mntsEntityBuilder);
// Create service instance with mocked entity builder and repository
repo = BDDMockito.mock(Repository.class);
myService = new MyService(entityBuilder, repo);
}
}
Mock Event Producer Serviceโ
Sending an event happens via EventProducerService, which will be a dependency to all implementaion classes that are configured with events (i.e commands, services and agents which are modelled to send events).
Below is an example of a command that involves sending an event, It has EventProducerService as a dependency.
@Service
public class FileNoteCommand extends FileNoteCommandBase {
private static final Logger log = LoggerFactory.getLogger(FileNoteCommand.class);
public FileNoteCommand(DomainEntityBuilder entityBuilder, EventProducerService eventProducer,
DomainEventBuilder eventBuilder, Repository repo, MinutesCommandBase minutesCommand) {
super(entityBuilder, eventBuilder, eventProducer, repo, minutesCommand);
}
Below is an example of testing a command and mocking event producer service.
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.BDDMockito;
public class FileNoteCommandTest {
// Declare dependencies that will be mocked
private EventProducerService eventProducer;
private DomainEntityBuilder entityBuilder;
private DomainEventBuilder eventBuilder;
private Repository repo;
// Command we want to test
private FileNoteCommand fileNoteCommand;
@BeforeEach
public void setup() {
// Mock event producer
eventProducer = BDDMockito.mock(EventProducerService.class);
// Mock other dependencies
repo = BDDMockito.mock(Repository.class);
entityBuilder = BDDMockito.mock(DomainEntityBuilder.class);
eventBuilder = BDDMockito.mock(DomainEventBuilder.class);
// If you were building your event with `DomainEventBuilder`, you need to mock calls that creates that event
// 1. Creating an mocked `MinutesLifecycleEvent`
mockedMinutesLifecycleEvent = new MinutesLifecycleEvent.MinutesLifecycleEventBuilder().build();
// Mocking call to create an event builder and return mocked MinutesLifecycleEvent instance
Mockito.when(eventBuilder.getMnts().getMinutesLifecycleEvent()).thenReturn(mockedMinutesLifecycleEvent);
// Create service instance with mocked entity builder and repository
fileNoteCommand = new FileNoteCommand(entityBuilder, eventBuilder, eventProducer repo);
}
}
Mock Authenticationโ
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.BDDMockito;
public class MyServiceTestWithMockingSecurity {
private DomainEntityBuilder entityBuilder;
private Repository repo;
private MyService myService;
@BeforeEach
public void setup() {
// Create needed mocks
entityBuilder = BDDMockito.mock(DomainEntityBuilder.class);
repo = BDDMockito.mock(Repository.class);
// Create service instance
myService = new MyService(entityBuilder, repo);
}
@Test
public void testGetUsernameFromContext() {
// Create a mock authentication object
Authentication authentication = BDDMockito.mock(Authentication.class);
BDDMockito.when(authentication.getName()).thenReturn("testuser");
// Set the SecurityContext with the mock authentication object
SecurityContext securityContext = mock(SecurityContext.class);
BDDMockito.when(securityContext.getAuthentication()).thenReturn(authentication);
SecurityContextHolder.setContext(securityContext);
// Call the method being tested
MyService service = new MyService();
OutputEntity result = service.execute();
// Verify that the correct username is returned
assertEquals("testuser", result.getUserName());
}
}
In this example, we're using Mockito to create a mock Authentication object and a mock SecurityContext object. We're then setting the SecurityContext to use the mock objects using SecurityContextHolder.setContext(). Finally, we're calling the method being tested and verifying that it returns the expected result.
Mock Integration Providerโ
Integration providers are classes that are generated for each uploaded Api Dependency that your service project needs to integrate with it (Api dependencies are uploaded within integration namespaces).
Below is an example of testing a Payment service with mocking Integration Provider for Payment Order Api.
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.BDDMockito;
public class PaymentServiceTest {
// Declare needed dependencies
private PaymentOrderApiPaymentorder paymentOrderApi;
private DomainEntityBuilder entityBuilder;
private Repository repo;
private PaymentServiceTest paymentSvc;
@BeforeEach
public void setup() {
paymentOrderApi = BDDMockito.mock(PaymentOrderApiPaymentorder.class);
// Create needed mocks
entityBuilder = BDDMockito.mock(DomainEntityBuilder.class);
repo = BDDMockito.mock(Repository.class);
// Create service instance with mocked entity builder, repository and paymentOrderApi
paymentSvc = new MyService(entityBuilder, repo, paymentOrderApi) ;
}
@Test
void testSuccessfulExecution() throws DisbursementTransactionNotFound {
// Mocking when calling `makePayment` operation that it will throw a RestClientException
BDDMockito.when(
paymentOrderApi.makePayment(BDDMockito.any(), BDDMockito.any())
).thenReturn(ResponseEntity.ok(null));
// Call paymentSvc service and excute it
OutputEntity result = paymentSvc.execute();
// Some assertions
// 1. Check transaction step was added
Assertions.assertThat(result.getTxnSteps()).hasAtLeastOneElementOfType(TransactionStep.class);
// 2. Check status still FAILED
String status = result.getTransactionStatus().toString();
Assertions.assertThat(status.contentEquals(TransactionStatus.FAILED.toString()));
}
@Test
public void testFailedExecution() {
// Mocking when calling `makePayment` operation that it will throw a RestClientException
BDDMockito.when(paymentOrderApi.makePayment(BDDMockito.any(), BDDMockito.any()))
.thenThrow(new RestClientException("Error occurred"));
// Assert that executing paymentSvc will result in an error thrown
Assertions.assertThatThrownBy(() -> paymentSvc.execute()).isInstanceOf(RestClientException.class);
}
}
You have successfully included a mocking library and mocked some of generated solution framework functionalities.