Preparing for Java Interview?

My books Grokking the Java Interview and Grokking the Spring Boot Interview can help

Download PDF

Difference between Mockito.mock(), @Mock and @MockBean annotation in Spring Boot

Hello guys, if you are wondering what is the difference between Mockito.mock(), @Mock and @MockBean annotation in Spring Boot then you have come to the right place. In the Spring Boot framework, @Mock and @MockBean are both annotations used for creating mock objects in unit testing scenarios. However, they are used in different contexts and have some differences in their behavior which you will find in this article. In the past, I have shared difference between @Controller and @Service as well @RequestParam vs @PathVariable and in this article, I will explain the difference between @Mock and @MockBean annotations in Spring Boot. To be honest, I love this kind of questions as it not only help on interviews but also help to learn the concept better and you should also love them too.

In the I have shared several Spring and Spring Boot resources like best Spring boot courses, best Spring Boot books, Spring Boot Interview questions and even Spring Boot projects If you have not checked them already, you can also check them to learn more about Spring and Spring Boot in depth.


What is @Mock Annotation?

The @Mock is an annotation provided by the Mockito library, which is a popular mocking framework used for unit testing in Spring Boot applications. It is used to create mock objects for dependencies that are not part of the Spring context. 

The @Mock annotation is typically used in conjunction with the MockitoJUnitRunner or MockitoExtension to initialize the mock objects. There is also a good chance that you may have used this annotation while mocking dependency on core Java application while writing unit test even without Spring Framework. 

Here's an example of how @Mock can be used in a Spring Boot test:

import static org.mockito.Mockito.*;

@RunWith(MockitoJUnitRunner.class)
public class UserServiceTest {

    @Mock
    private UserRepository userRepository;

    @InjectMocks
    private UserService userService;

    @Test
    public void testGetUserById() {
        // Given
        User mockedUser = new User("John", "Doe", 25);
        when(userRepository.findById(1L)).thenReturn(Optional.of(mockedUser));
        
        // When
        User result = userService.getUserById(1L);

        // Then
        assertNotNull(result);
        assertEquals("John", result.getFirstName());
        assertEquals("Doe", result.getLastName());
        assertEquals(25, result.getAge());
        verify(userRepository).findById(1L); // Verify that the findById method was called
    }
}

In this example, @Mock is used to create a mock object of UserRepository, which is a dependency of UserService. The @RunWith(MockitoJUnitRunner.class) annotation is used to enable Mockito's JUnit runner, and @InjectMocks is used to inject the mock objects into the test subject (UserService in this case). 

The when() method is used to define the behavior of the mock object, and the verify() method is used to verify that certain methods were called on the mock object during the test.


What is @MockBean annotation? What does it do?

The @MockBean is a Spring Boot-specific annotation provided by the Spring Boot Test module. It is used to create mock objects for dependencies that are part of the Spring context, such as beans declared in the application's configuration or beans created by Spring Boot auto-configuration. @MockBean allows for the replacement of actual beans with mock objects during unit testing.

Here's an example of how @MockBean can be used in a Spring Boot test:

@SpringBootTest
public class UserServiceIntegrationTest {

    @Autowired
    private UserService userService;

    @MockBean
    private UserRepository userRepository;

    @Test
    public void testGetUserById() {
        // Given
        User mockedUser = new User("John", "Doe", 25);
        when(userRepository.findById(1L)).thenReturn(Optional.of(mockedUser));

        // When
        User result = userService.getUserById(1L);

        // Then
        assertNotNull(result);
        assertEquals("John", result.getFirstName());
        assertEquals("Doe", result.getLastName());
        assertEquals(25, result.getAge());
        verify(userRepository).findById(1L); // Verify that the findById method was called
    }
}

In this example, @MockBean is used to create a mock object of UserRepository, which is a dependency of UserService. The @SpringBootTest annotation is used to enable full Spring Boot integration testing. The when() method is used to define the behavior of the mock object, and the verify() method is used to verify that certain methods were called on the mock object during the test.


What is Mockito.mock()? What does it do?

If you have used Mockito before then you may be familiar with this method but for those who are not , Mockito.mock() is a method provided by the Mockito framework, which is a popular mocking framework for Java-based unit testing.

It allows developers to create mock objects, which are objects that simulate the behavior of real objects but do not have actual implementation logic. Mock objects are used in unit testing to isolate the code being tested from its dependencies, so that tests can be executed in isolation without relying on real external components.

The Mockito.mock() method is used to create a mock object of a given class or interface. It takes the class or interface as an argument and returns an instance of that class or interface with all of its methods stubbed out with default behavior, such as returning null, 0, or an empty collection. Developers can then configure the mock object's behavior using Mockito's API to define specific expectations and responses for method invocations during test cases.

Here's an example of how Mockito.mock() can be used in Java and Spring Boot application

// Example interface
public interface GreetingService {
    String greet(String name);
}

// Test case using Mockito.mock()
@Test
public void testGreet() {
    // Create a mock object of MyService
    GreetingService myServiceMock = Mockito.mock(GeetingService.class);

    // Define behavior for the greet() method
    Mockito.when(myServiceMock.greet(Mockito.anyString())).thenReturn("Hello, ");

    // Test the method that depends on MyService
    MyClass myClass = new MyClass(myServiceMock);
    String result = myClass.greet("John");

    // Verify the expected behavior
    Mockito.verify(myServiceMock).greet("John");
    Assert.assertEquals("Hello, John", result);
}

In this example, Mockito.mock(MyService.class) is used to create a mock object of the GreetingService interface, and Mockito.when() is used to define the behavior of the greet() method on the mock object. The myServiceMock object is then passed as a dependency to the MyClass object being tested, and its behavior is verified using Mockito.verify() and assertions.


Difference between @Mock and @MockBean annotation in Spring Boot

Here are the key differences between @Mock and @MockBean annotations in Spring Boot and Spring Framework are:

1. Context
@Mock is used for mocking objects that are not part of the Spring context, while @MockBean is used for mocking objects that are part of the Spring context.  It is used in plain JUnit tests with the Mockito framework. It is also not aware of the Spring context and is typically used for unit testing isolated components without the need for a full Spring context setup.


2. Integration with Spring Boot
@MockBean is a Spring Boot-specific annotation that provides integration with the Spring Boot Test module, allowing for seamless mocking of Spring beans in Spring Boot applications.


3. Initialization
@Mock requires the use of MockitoJUnitRunner or MockitoExtension for initializing the mock objects, while @MockBean is automatically initialized by the Spring Boot Test framework during the test context setup.


4. Bean replacement
@MockBean replaces the actual beans in the Spring context with mock objects during testing, while @Mock does not impact the actual beans in the Spring context.

Here is a nice diagram which shows highlights the important difference of @Mock and @MockBean annotations in Spring:

Difference between Mockito.mock(), @Mock and @MockBean annotation in Spring Boot




Things to Remember while using @Mock and @MockBean annotations 

When using @Mock and @MockBean annotations in Spring Boot tests, there are some important things to keep in mind:

1. Proper usage
@Mock is used for plain JUnit tests with the Mockito framework, while @MockBean is used in Spring Boot tests for mocking dependencies of a Spring application context.

2. Integration with Spring context
@MockBean is aware of the Spring context and allows for mocking of beans that are part of the application context, such as @Service, @Repository, or @Component annotated beans. On the other hand, @Mock is not aware of the Spring context and is used for unit testing isolated components without the need for a full Spring context setup.

3. Proper import
@Mock is imported from the org.mockito package, while @MockBean is imported from the org.springframework.boot.test.mock.mockito package. Make sure to import the correct annotation for the respective usage.

4. Proper setup
When using @MockBean, Spring Boot automatically replaces the actual bean in the Spring context with the mock bean, allowing for proper dependency injection. However, with @Mock, the mock object needs to be manually injected into the test instance using the @InjectMocks annotation or by calling MockitoAnnotations.initMocks(this) in the test setup.

5. Resetting mocks
Both @Mock and @MockBean create mock objects that can be used to define the behavior of the mocked objects. It's important to reset the mocks after each test to avoid test interdependencies and ensure clean test execution.

6. Use sparingly
Mocking should be used judiciously and only when necessary. Overuse of mocks can lead to overly complex tests and reduced test effectiveness. It's important to strike a balance between using mocks and real dependencies in your tests to ensure meaningful and reliable test results.

7. Test coverage
When using mocks, be mindful of the test coverage. Mocks should not replace real testing of actual implementations. It's important to have a balance between unit tests with mocks and integration tests with real dependencies to ensure comprehensive test coverage.

By keeping these considerations in mind, you can effectively use @Mock and @MockBean annotations in your Spring Boot tests to create mock objects and effectively test your application's behavior and interactions.


That;s all about the difference between @Mock and @MockBean annotation in Spring Boot. Just remember that @Mock is used for mocking objects that are not part of the Spring context, while @MockBean is used for mocking objects that are part of the Spring context in Spring Boot applications. @MockBean provides seamless integration with the Spring Boot Test framework and allows for easy replacement of actual beans with mock objects during testing.


Other Spring Framework articles you may like to explore 


    Thanks for reading this article so far. If you find this Difference between @Mock and @MockBean annotation in Spring Boot
     tutorial useful, please share them with your friends and colleagues. If you have any questions or feedback, then please drop a note.

    P. S. - If you are new to Spring Boot  and Hibernate and keen to learn both Spring and Hibernate in depth, then you can also check out this list of best Spring and Hibernate online courses for Java developers. You will save a lot of time. 

    No comments:

    Post a Comment

    Feel free to comment, ask questions if you have any doubt.