From 9ad36c808c7a2bc162119cfb79433d35d7d558dc Mon Sep 17 00:00:00 2001 From: Badri Paudel Date: Sun, 24 Mar 2024 11:38:18 +0545 Subject: [PATCH] @ExtendWith(MockitoExtension.class) is used instead of @SpringBootTest not to load the whole application context, and a separate MockitoTest.java added just to demonstrate and experiment. --- .../info/keeper/service/AdminService.java | 6 ++ .../info/keeper/mockito_test/MockitoTest.java | 70 +++++++++++++++++++ .../info/keeper/service/AdminServiceTest.java | 6 +- .../info/keeper/service/UserServiceTest.java | 5 +- 4 files changed, 82 insertions(+), 5 deletions(-) create mode 100644 src/test/java/info/keeper/mockito_test/MockitoTest.java diff --git a/src/main/java/info/keeper/service/AdminService.java b/src/main/java/info/keeper/service/AdminService.java index 813da0c..897b18a 100644 --- a/src/main/java/info/keeper/service/AdminService.java +++ b/src/main/java/info/keeper/service/AdminService.java @@ -4,6 +4,7 @@ import info.keeper.repositories.AdminRepository; import org.springframework.stereotype.Service; +import javax.annotation.PostConstruct; import java.security.Principal; import java.util.Date; @@ -21,4 +22,9 @@ public void saveAdminMessage(AdminMessage adminMessage, Principal principal) { adminMessage.setPostedBy(principal.getName().split("@")[0]); // show only before @ adminRepository.save(adminMessage); } + + @PostConstruct + public void someSetUp() { + System.out.println("<<<<< Some Setup here >>>>>"); + } } diff --git a/src/test/java/info/keeper/mockito_test/MockitoTest.java b/src/test/java/info/keeper/mockito_test/MockitoTest.java new file mode 100644 index 0000000..bba7838 --- /dev/null +++ b/src/test/java/info/keeper/mockito_test/MockitoTest.java @@ -0,0 +1,70 @@ +package info.keeper.mockito_test; + +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.*; +/** + * @ExtendWith(MockitoExtension.class) is used to integrate Mockito with JUnit 5, + * allowing you to use Mockito's mocking capabilities within your JUnit 5 tests. + * It initializes mocks annotated with @Mock, verifies interactions, + * and allows you to use Mockito's verification and stubbing features in your tests. + * As opposed to loading entire application context loading using @SpringBootTest + * //@SpringBootTest + */ +@ExtendWith(MockitoExtension.class) +public class MockitoTest { + + static List mockedList; + + @BeforeAll + @Test + public static void itShouldMockTheListAndAssertThatItIsNotNull() { + mockedList = mock(List.class); + assertNotNull(mockedList); + } + + @DisplayName("Experiment the mocking and verify the behaviours") + @Test + public void itShouldPerformListOperationsAndVerifyTheMockingResult(){ + mockedList.clear(); + mockedList.add("ANY_ITEM"); + mockedList.add(anyString()); + mockedList.add("ANOTHER_ITEM"); + verify(mockedList, times(1)).clear(); // clear was called once + verify(mockedList, times(3)).add(anyString()); // add was called thrice + verify(mockedList, times(1)).add("ANY_ITEM"); // but add with argument "ANY_ITEM" was called only ONCE + /** + * IT FAILS because NOT_EXISTING_ITEM has not been added at all, even though anyString() has been added but + * it doesn't work the way it works the other way around. + */ + // verify(mockedList, times(1)).add("NOT_EXISTING_ITEM"); FAILS + } + + @DisplayName("Manipulate the list and do the stubbing") + @Test + public void itShouldPerformActionOnListAndDoStubbingAndVerify() { + when(mockedList.get(0)).thenReturn("ANY_ITEM"); + when(mockedList.get(100)).thenThrow(new IndexOutOfBoundsException()); + } + + @Test + @DisplayName("Argument matchers experiment") + public void itShouldPerformArgumentMatcherOperationsAndVerify() { + when(mockedList.get(anyInt())).thenReturn(true); + when(mockedList.get(200)).thenThrow(new IndexOutOfBoundsException()); + assertTrue((boolean) mockedList.get(100)); + // reset(mock); mock can also be reset, it this time, all stubbing and mocking will be forgotten. + when(mockedList.add(eq("test"))).thenReturn(true); + when(mockedList.add("RANDOM")).thenReturn(false); + when(mockedList.add(anyString())).thenReturn(false); + } + +} diff --git a/src/test/java/info/keeper/service/AdminServiceTest.java b/src/test/java/info/keeper/service/AdminServiceTest.java index c667c74..3ec08ce 100644 --- a/src/test/java/info/keeper/service/AdminServiceTest.java +++ b/src/test/java/info/keeper/service/AdminServiceTest.java @@ -5,17 +5,17 @@ import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; -import org.mockito.Mockito; -import org.springframework.boot.test.context.SpringBootTest; +import org.mockito.junit.jupiter.MockitoExtension; import java.security.Principal; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.*; -@SpringBootTest +@ExtendWith(MockitoExtension.class) class AdminServiceTest { @InjectMocks AdminService adminService; diff --git a/src/test/java/info/keeper/service/UserServiceTest.java b/src/test/java/info/keeper/service/UserServiceTest.java index b12f6ed..a1ed81e 100644 --- a/src/test/java/info/keeper/service/UserServiceTest.java +++ b/src/test/java/info/keeper/service/UserServiceTest.java @@ -6,15 +6,16 @@ import info.keeper.models.User; import info.keeper.repositories.UserRepository; import org.junit.jupiter.api.*; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; -import org.springframework.boot.test.context.SpringBootTest; +import org.mockito.junit.jupiter.MockitoExtension; /** * REF: https://www.baeldung.com/java-spring-mockito-mock-mockbean (Mockito.Mock vs @Mock syntax) * REF : https://stackoverflow.com/questions/16467685/difference-between-mock-and-injectmocks (@InjectMocks and @Mock) */ -@SpringBootTest +@ExtendWith(MockitoExtension.class) class UserServiceTest { // This UserRepository will be mocked (for some method of it, we will be returning the result of the mock and not the real db call) @Mock