How to test with SpringBoot
There are several ways to test a Spring Boot application, including unit tests, integration tests, and end-to-end tests.
Unit tests can be written using JUnit and test individual components of the application, such as service or repository classes. Spring Boot provides the @SpringBootTest annotation to enable loading of the application context for these tests.
Integration tests can be written using JUnit and the Spring Test and Spring Boot Test libraries. These tests run against the entire application and can test the interaction between multiple components. The @SpringBootTest annotation can also be used for integration tests.
End-to-end tests can be written using libraries such as Selenium or Cucumber and test the application from the perspective of an end user. These tests typically run against a deployed application and test the UI and user interactions.
You can also use mockMvc to test your controllers.
It is a powerful way to easily test Spring MVC controllers without starting a full HTTP server.
In summary, you can use JUnit and the Spring Test and Spring Boot Test libraries to write unit and integration tests, and use libraries such as Selenium or Cucumber for end-to-end tests. You can also use mockMvc to test your controllers.
Mockito.mock() example code
Here is an example of how to use Mockito to create a mock object:
import org.mockito.Mockito; public class ExampleTest { @Test public void testExample() { // Create a mock object of the class you want to test MyService myService = Mockito.mock(MyService.class); // Set up the mock object's behavior Mockito.when(myService.doSomething()).thenReturn("Mocked result"); // Use the mock object in your test Example example = new Example(myService); String result = example.useMyService(); assertEquals("Mocked result", result); } }
In this example, we are creating a mock object of the MyService class using the Mockito.mock() method. We are then using the when() method to specify the behavior of the mock object when the doSomething() method is called. In this case, we are telling the mock to return the string “Mocked result” when doSomething() is called.
In the test method, we are creating an instance of the class Example and passing it the mock object of MyService, then we are calling the useMyService() method of Example class and assert the result with the mocked result.
Mocking allows you to isolate the component you are testing, so that you can test its behavior independently of other components.
Please note that this is just an example and the actual implementation of the classes and methods used in this example might be different based on your use case.
@Mock example code
Here is an example of how to use the @Mock annotation to create a mock object:
import org.junit.jupiter.api.Test; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; @ExtendWith(MockitoExtension.class) public class ExampleTest { @Mock private MyService myService; @InjectMocks private Example example; @Test public void testExample() { // Set up the mock object's behavior Mockito.when(myService.doSomething()).thenReturn("Mocked result"); // Use the mock object in your test String result = example.useMyService(); assertEquals("Mocked result", result); } }
In this example, we are using the @Mock annotation to create a mock object of the MyService class. We are then using the when() method to specify the behavior of the mock object when the doSomething() method is called. In this case, we are telling the mock to return the string “Mocked result” when doSomething() is called.
We also use the @InjectMocks annotation to inject the mock objects in the class we want to test Example.
In the test method, we are calling the useMyService() method of Example class and assert the result with the mocked result.
The @ExtendWith(MockitoExtension.class) is used to enable the usage of annotations in junit5.
Mocking allows you to isolate the component you are testing, so that you can test its behavior independently of other components.
@MockBean example code
Here is an example of how to use the @MockBean annotation to create a mock object in a Spring Boot application:
import org.junit.jupiter.api.Test; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.test.context.junit.jupiter.SpringExtension; @ExtendWith(SpringExtension.class) @SpringBootTest public class ExampleTest { @MockBean private MyService myService; @Autowired private Example example; @Test public void testExample() { // Set up the mock object's behavior Mockito.when(myService.doSomething()).thenReturn("Mocked result"); // Use the mock object in your test String result = example.useMyService(); assertEquals("Mocked result", result); } }
In this example, we are using the @MockBean annotation to create a mock object of the MyService class in a Spring Boot application. The @MockBean annotation can only be used in the context of a Spring Boot test and is used to replace a bean in the ApplicationContext with a mock.
We also use the @Autowired annotation to inject the Example class in the test case.
In the test method, we are calling the useMyService() method of Example class and assert the result with the mocked result.
The @ExtendWith(SpringExtension.class) and @SpringBootTest is used to enable the usage of annotations in junit5 and to load the spring context.
Mocking allows you to isolate the component you are testing, so that you can test its behavior independently of other components.
Testing with Mock for SpringBoot RestAPI Controller
Here is an example of how to use mock objects to test a Spring Boot REST API controller:
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import static org.mockito.Mockito.when; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @ExtendWith(MockitoExtension.class) public class ExampleControllerTest { @Mock private MyService myService; @InjectMocks private ExampleController exampleController; private MockMvc mockMvc; @BeforeEach public void setUp() { mockMvc = MockMvcBuilders.standaloneSetup(exampleController).build(); } @Test public void testGetData() throws Exception { // Set up the mock object's behavior when(myService.getData()).thenReturn("Mocked data"); // Test the controller's GET endpoint mockMvc.perform(get("/data")) .andExpect(status().isOk()) .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8)) .andExpect(content().string("Mocked data")); } }
In this example, we are using the @Mock annotation to create a mock object of the MyService class, and the @InjectMocks annotation to inject the mock object into the ExampleController class.
We are also using the MockMvc class from the Spring Test framework to test the controller’s GET endpoint. MockMvcBuilders.standaloneSetup(controller) is used to set up a MockMvc instance to test the ExampleController.
In the test method, we are setting up the behavior of the mock object using when(myService.getData()).thenReturn(“Mocked data”); and then we are testing the /data endpoint by performing a GET request to the endpoint and asserting that the status code is 200 OK and the content type and body of the response are as expected.
This way you can test your RestAPI Controllers without starting a full HTTP server and without depending on any external resources.
Please note that this is just an example and the actual implementation of the classes and methods used in this example might be different based on your use case.
Testing Service Layer with SpringBoot and Mock
Here is an example of how to use mock objects to test a service layer in a Spring Boot application:
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) public class MyServiceTest { @Mock private MyRepository myRepository; @InjectMocks private MyService myService; @Test public void testGetData() { when(myRepository.findData()).thenReturn("Mocked data"); String result = myService.getData(); assertEquals("Mocked data", result); } }
In this example, we are using the @Mock annotation to create a mock object of the MyRepository class, and the @InjectMocks annotation to inject the mock object into the MyService class.
In the test method, we are setting up the behavior of the mock object using when(myRepository.findData()).thenReturn(“Mocked data”); and then we are testing the getData() method of the MyService class by calling it and asserting that the result is equal to “Mocked data”.
This way you can test your Service Layer without starting a full HTTP server and without depending on any external resources.
Testing Repository Layer with SpringBoot and Mock
Here is an example of how to use mock objects to test a repository layer in a Spring Boot application:
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.RowMapper; import java.sql.ResultSet; import java.sql.SQLException; import java.util.List; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) public class MyRepositoryTest { @Mock private JdbcTemplate jdbcTemplate; @InjectMocks private MyRepository myRepository; @Test public void testFindData() { when(jdbcTemplate.query(anyString(), any(RowMapper.class))).thenReturn(List.of("Mocked data")); Listresult = myRepository.findData(); assertEquals(List.of("Mocked data"), result); } }
In this example, we are using the @Mock annotation to create a mock object of the JdbcTemplate class, and the @InjectMocks annotation to inject the mock object into the MyRepository class.
In the test method, we are setting up the behavior of the mock object using when(jdbcTemplate.query(anyString(), any(RowMapper.class))).thenReturn(List.of(“Mocked data”)); and then we are testing the findData() method of the MyRepository class by calling it and asserting that the result is equal to a list containing one element “Mocked data”.
Mocking Exception Throwing with Non-Void return
Here is an example of how to use mock objects to test a service layer that throws an exception:
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) public class MyServiceTest { @Mock private MyRepository myRepository; @InjectMocks private MyService myService; @Test public void testGetData() { when(myRepository.findData()).thenThrow(new IllegalArgumentException("Mocked exception")); assertThrows(IllegalArgumentException.class, () -> myService.getData()); } }
In this example, we are using the @Mock annotation to create a mock object of the MyRepository class, and the @InjectMocks annotation to inject the mock object into the MyService class.
In the test method, we are setting up the behavior of the mock object using when(myRepository.findData()).thenThrow(new IllegalArgumentException(“Mocked exception”)); and then we are testing the getData() method of the MyService class by calling it inside an assertThrows block and asserting that it throws an IllegalArgumentException with the message “Mocked exception”.
This way you can test your service layer and the exception handling of it.
Mocking Exception Throwing with Void return
Here is an example of how to use mock objects to test a service layer that throws an exception when a void method is called:
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.Mockito.doThrow; @ExtendWith(MockitoExtension.class) public class MyServiceTest { @Mock private MyRepository myRepository; @InjectMocks private MyService myService; @Test public void testDeleteData() { doThrow(new IllegalArgumentException("Mocked exception")).when(myRepository).deleteData(); assertThrows(IllegalArgumentException.class, () -> myService.deleteData()); } }
In this example, we are using the @Mock annotation to create a mock object of the MyRepository class, and the @InjectMocks annotation to inject the mock object into the MyService class.
In the test method, we are setting up the behavior of the mock object using doThrow(new IllegalArgumentException(“Mocked exception”)).when(myRepository).deleteData(); and then we are testing the deleteData() method of the MyService class by calling it inside an assertThrows block and asserting that it throws an IllegalArgumentException with the message “Mocked exception”.
Spy to throw an exception example code
Here is an example of how to use a spy object to test a service layer that throws an exception when a void method is called:
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Spy; import org.mockito.junit.jupiter.MockitoExtension; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.Mockito.doThrow; @ExtendWith(MockitoExtension.class) public class MyServiceTest { @Spy private MyRepository myRepository; @InjectMocks private MyService myService; @Test public void testDeleteData() { doThrow(new IllegalArgumentException("Mocked exception")).when(myRepository).deleteData(); assertThrows(IllegalArgumentException.class, () -> myService.deleteData()); } }
In this example, we are using the @Spy annotation to create a spy object of the MyRepository class, and the @InjectMocks annotation to inject the spy object into the MyService class.
AssertJ Exception Assertions example code
Here is an example of how to use AssertJ to assert that a specific exception is thrown in a test case:
import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThatThrownBy; public class MyServiceTest { @Test public void testDeleteData() { MyService myService = new MyService(); assertThatThrownBy(() -> myService.deleteData()) .isInstanceOf(IllegalArgumentException.class) .hasMessage("Invalid argument"); } }
In this example, we are using the assertThatThrownBy method from AssertJ to assert that the deleteData() method of the MyService class throws an IllegalArgumentException with the message “Invalid argument”.
We are wrapping the method call inside the assertThatThrownBy block, this way AssertJ will check if any exception was thrown, and if so it will check the type and message of the exception.
This way you can use a more expressive and readable way to assert the exceptions thrown by your code.