【Mockito】@Mock 和 @MockBean 的区别与 @MockBean 的使用时机

该文章已生成可运行项目,

前言

由于历史原因,@Mock 和 @MockBean 都会出现在项目代码里,这里记录下具体的区别。并突出 @MockBean 在 Spring Boot 中的使用时机

@Mock

来自于 Mockito 的包,本质上和以下代码没有区别。

MyService myservice = Mockito.mock(MyService.class);

@Mock 与 MockitoJUnitRunner 配合使用

如果发现 @Mock 不生效,可以检查一下 Runner 有没有配置正确

@RunWith(MockitoJUnitRunner.class)
@SpringBootTest(classes = MyService.class)
public class MyClassTest {

    @Mock
    MyService myService;

    @Test
    public void hello() {
        Objects.requireNonNull(myService);
    }
}
  • 以上代码的等价写法:
@RunWith(SpringRunner.class)
@SpringBootTest(classes = MyClassTest.class)
public class MyClassTest {

    @Mock
    MyService myService;

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void hello() {
        Objects.requireNonNull(myService);
    }
}

@MockBean

该注解来自于 spring-boot-test 的包。用于跟 Spring 容器集成。那什么时候需要跟 Spring 容器集成呢?回答这个问题就知道 @MockBean 的应用场景了。

@Mock 与 Spring Boot Test 配合使用

值得一提的是 Spring Boot Test 中 @WebMvcTest 是用于只测试 Spring MVC 功能的注解。这个注解的来由是 Junit 希望让测试变得轻量,不需要 Spring 加载所有的 bean 再执行测试。同样类型的注解还有 @JdbcTest 和 @DataMongoTest

@RunWith(SpringRunner.class)
@WebMvcTest(FooController.class)
public class FooControllerTest {

    @Autowired
    private MockMvc mvc;

    @MockBean
    private FooService fooServiceMock;

    @Test
    public void testExample() throws Exception {
         Foo mockedFoo = new Foo("one", "two");

         Mockito.when(fooServiceMock.get(1))
                .thenReturn(mockedFoo);

         mvc.perform(get("foos/1")
            .accept(MediaType.TEXT_PLAIN))
            .andExpect(status().isOk())
            .andExpect(content().string("one two"));
    }

}

@MockBean 的使用时机

根据上述代码,可以理解 @MockBean 做了些什么:

// 把 Spring MVC 的bean 注入到容器中用于测试
@WebMvcTest(FooController.class)
public class FooControllerTest {
	
	// 补充一个额外的bean用于支持测试
    @MockBean
    private FooService fooServiceMock;
	
}
本文章已经生成可运行项目
`@Mock` `@MockBean` 是两种常用的 Mock 注解,但它们适用于不同的测试场景框架,主要区别如下: --- ### **1. `@Mock`(来自 Mockito)** - **适用框架**:纯 Mockito 测试(不涉及 Spring 容器) - **使用场景**:普通单元测试,不依赖 Spring 上下文 - **初始化方式**: - 需要配合 `MockitoAnnotations.openMocks(this)` 或 `@ExtendWith(MockitoExtension.class)` 使用 - **特点**: - 轻量级,启动快 - 不注册到 Spring 容器,仅用于当前测试类 - **示例**: ```java @ExtendWith(MockitoExtension.class) class MyTest { @Mock private UserRepository userRepository; // 纯 MockitoMock 对象 } ``` --- ### **2. `@MockBean`(来自 Spring Boot Test)** - **适用框架**:Spring Boot 集成测试(需要 Spring 容器) - **使用场景**: - 测试需要启动 Spring 上下文时(如 `@SpringBootTest`) - 需要替换 Spring 容器中的真实 Bean - **初始化方式**: - 由 Spring 容器管理,自动替换应用上下文中的同名 Bean - **特点**: - 集成到 Spring 环境,适合测试 Controller、Service 等 Spring 组件 - 会触发 Spring 上下文重启(可能影响测试速度) - **示例**: ```java @SpringBootTest class MyIntegrationTest { @MockBean private UserRepository userRepository; // 替换 Spring 容器中的真实 Bean } ``` --- ### **核心区别总结** | 特性 | `@Mock` | `@MockBean` | |---------------------|----------------------------------|---------------------------------| | **所属框架** | Mockito | Spring Boot Test | | **是否需要 Spring** | 否 | 是 | | **测试类型** | 单元测试 | 集成测试 | | **Bean 替换** | 不涉及 Spring Bean | 替换 Spring 容器中的真实 Bean | | **执行速度** | 快(无容器启动) | 慢(需启动 Spring 上下文) | --- ### **如何选择?** - 如果测试 **不依赖 Spring 环境**(如纯 Service 逻辑测试),用 `@Mock`(更快)。 - 如果测试 **需要 Spring 上下文**(如 Controller、`@Autowired` 依赖),用 `@MockBean`。 --- ### **常见问题** 1. **混用会怎样?** - `@Mock` + `@SpringBootTest`:Mock 对象不会被 Spring 管理,可能导致 NPE。 - `@MockBean` 在非 Spring 测试中:直接报错,因为需要容器支持。 2. **性能影响** `@MockBean` 会导致 Spring 上下文重建,建议在集成测试中合理使用(如通过 `@TestConfiguration` 减少不必要的 Mock)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值