Difference Between @Mock and @MockBean in Spring Testing
When writing tests in a Spring application, you may need to create mock objects to simulate the behavior of dependencies. Two common annotations used for this purpose are @Mock and @MockBean. Though they might seem similar, they serve different purposes and are used in distinct contexts. This article provides a detailed comparison between @Mock and @MockBean.
Introduction to Mocking in Spring
Mocking is an essential part of unit testing, allowing developers to isolate the component under test by replacing dependencies with mock objects. In Spring, @Mock and @MockBean are frequently used annotations to achieve this, each fitting specific testing scenarios.
What is @Mock?
Usage Context
- Typically used with the Mockito framework.
- Mainly used in unit tests where the Spring context is not needed or not loaded.
Scope and Configuration
- Creates a mock instance of a class or interface.
- Configured using
@ExtendWith(MockitoExtension.class)in JUnit 5 or@RunWith(MockitoJUnitRunner.class)in JUnit 4.
Application and Injection
- Can be injected into the test class using
@InjectMocksto inject the mocks into the class being tested.
Example:
import static org.mockito.Mockito.*;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.junit.jupiter.api.extension.ExtendWith;
@ExtendWith(MockitoExtension.class)
public class MyServiceTest {
@Mock
private MyRepository myRepository;
@InjectMocks
private MyService myService;
@Test
void testMyService() {
when(myRepository.findSomething()).thenReturn("mocked value");
String result = myService.doSomething();
assertEquals("mocked value", result);
}
}
What is @MockBean?
Usage Context
- Specifically designed for use with the Spring Boot testing framework.
- Commonly used in integration tests where the Spring context is loaded.
Scope and Configuration
- Creates a mock instance and adds it to the Spring application context.
- Used with annotations like
@SpringBootTest,@WebMvcTest,@DataJpaTest, etc.
Application and Injection
- Allows for replacing specific beans within the Spring context with mocks.
- Automatically injected into the Spring context, making it available for autowiring in the test and the beans under test.
Example:
import static org.mockito.Mockito.*;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
public class MyServiceIntegrationTest {
@MockBean
private MyRepository myRepository;
@Autowired
private MyService myService;
@Test
void testMyService() {
when(myRepository.findSomething()).thenReturn("mocked value");
String result = myService.doSomething();
assertEquals("mocked value", result);
}
}
Summary of Differences
@Mock:
- Used for unit testing with Mockito.
- Does not involve the Spring context.
- Configured with
@ExtendWithor@RunWith.
@MockBean:
- Used for integration testing with Spring Boot.
- Adds the mock to the Spring context.
- Used with
@SpringBootTestand other Spring Boot test annotations.
Choosing Between @Mock and @MockBean
- Use
@Mockfor isolated unit tests where you don’t need the full Spring context. - Use
@MockBeanwhen you need to mock specific beans while leveraging Spring’s dependency injection in integration tests.