# Mocking and Testing in Spring ## Possible ways of doing mocking with Spring: ### 1. Mockito.mock() **Where?** Inside of a test, you don't list your dependencies as class fields. **Rating:** 3/5 => It's easy to understand, there is no high level function that uses black magic to work, but it is prone to code duplication and you don't have any framework check on whether you really need that stub or not. ```java @Test void createOrderSetsTheCreationDate() { OrderRepository orderRepository = mock(OrderRepository.class); OrderService orderService = new OrderService(orderRepository); when(orderRepository.save(any(Order.class))).then(returnsFirstArg()); Order order = new Order(); Order savedOrder = orderService.create(order); assertNotNull(savedOrder.getCreationDate()); verify(orderRepository).save(order); verifyNoMoreInteractions(orderRepository); } ``` ### @Mock and @InjectMocks annotations **Where?** On a field in the test class **How does it work?** It is a shorthand for Mockito.mock() and allows us to create a mock object of a class **Rating:** 4/5 => It uses higher level functionality by bringing in the two annotations, but for instantiating the mocks you still need a helper method, that we can set up in a setup method annotated with @BeforeEach, but still doesn't care if the mock is unnecessary ```java @Mock private OrderRepository orderRepository; @InjectMocks private OrderService orderService; @BeforeEach void setupTest() { MockitoAnnotations.openMocks(this); } @Test void createOrderMethodSetsTheCreationDate() { when(orderRepository.save(any(Order.class))).then(returnsFirstArg()); Order order = new Order(); Order savedOrder = orderService.create(order); assertNotNull(savedOrder.getCreationDate()); } } ``` ### Extend with MockitoExtension.class **Where?** On a class and the fields **How does it work?** It is a shorthand for Mockito.mock() and allows us to create a mock object of a class **Rating:** 5/5 => Clean code, using high level annotations and the extension of the Mockito, instantiating your mocks right away, while providing you with warning in case of unnecessary mocks ```java @ExtendWith(MockitoExtension.class) public class MockWithExtendWithAnnotation { @Mock private OrderRepository orderRepository; @InjectMocks private OrderService orderService; @Test void createOrderMethodSetsTheCreationDate() { when(orderRepository.save(any(Order.class))).then(returnsFirstArg()); Order order = new Order(); Order savedOrder = orderService.create(order); assertNotNull(savedOrder.getCreationDate()); } } ``` ## Glossary of testing related annotations with Junit5: 1. ***@ExtendWith(SpringExtension.class)*** - This annotation is used to run the tests with the Spring test extension, which provides a Spring application context for the tests. 2. ***@SpringBootTest*** - This annotation is used to start up the Spring application context and load the beans into it. It allows you to write integration tests that test the entire application. 3. ***@WebMvcTest*** - This annotation is used to load only the Spring MVC components of the application context, which allows you to write unit tests for the controller layer. 4. ***@DataJpaTest*** - This annotation is used to load only the Spring Data JPA components of the application context, which allows you to write unit tests for the repository layer. 5. ***@MockBean*** - This annotation is used to create a Mockito mock object of a bean, which allows you to replace the real implementation with a mock object in the Spring application context. 6. ***@Test*** - This annotation is used to indicate that a method is a test method. 7. ***@BeforeEach*** - This annotation is used to indicate that a method should be run before each test method is run. 8. ***@AfterEach*** - This annotation is used to indicate that a method should be run after each test method is run. 9. ***@InjectMocks*** - This annotation is used to inject the mock objects into the class under test, based on the type of each mock object and the type of each field in the class under test. 10. ***@Mock*** - This annotation is used to create a mock object of a dependency 11. ***@AutoConfigureMockMvc(addFilters = false)*** - This annotation is used to make the tests in this class ignore the spring security filters