You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MockMVC测试:@MockBean与@Mock混用致Mockito When失效问题

问题描述

我编写了如下MockMVC测试类:

@SpringBootTest
@AutoConfigureMockMvc
class PersonControllerShould {

    @MockBean
    private PersonActivity personActivity;

    @MockBean
    private PersonMapper mapper;

    @Mock
    private MongoConfig mongoconfig;

    @Autowired
    private MockMvc mockMvc;

    @BeforeEach
    public void setUp() {
        MockitoAnnotations.openMocks(this);
    }
    
    // tests...
    
}

其中PersonActivity和PersonMapper均为Spring管理的@Component;MongoConfig类标注了@ConfigurationProperties(prefix = "cosmosdb")与@ConstructorBinding,并非Spring组件,因此使用@Mock进行Mock。但针对MongoConfig编写的Mockito When语句无法生效,想请教两个问题:

  1. 该失效问题的原因是什么?
  2. MockMVC测试类中是否可以同时使用@MockBean和@Mock?

参考Controller代码:

@CrossOrigin(origins = "*")
@RestController
@RequestMapping(value = "/person")
public class PersonController {

    private final PersonActivity personActivity;
    private final PersonMapper mapper;
    private final MongoConfig mongoconfig;

    public PersonController(
            @Autowired PersonActivity personActivity,
            @Autowired PersonMapper mapper,
            @Autowired MongoConfig mongoconfig
    ) {
        this.personActivity = personActivity;
        this.mapper = mapper;
        this.mongoconfig = mongoconfig;
    }
    
    // rest mappings 

}
问题解答

一、MongoConfig Mock失效的原因

你用@Mock创建的MongoConfig实例根本没被Spring容器注入到PersonController里,具体原因如下:

  • 虽然MongoConfig没有标注@Component这类Spring组件注解,但它搭配了@ConfigurationProperties和@ConstructorBinding,再加上你在Controller中用@Autowired注入了它,Spring Boot会自动将其作为bean纳入容器管理,生成对应的实例。
  • 测试类里的@Mock是Mockito原生注解,只会在当前测试类内部创建一个普通的模拟对象,不会把这个对象注册到Spring容器中。而PersonController是从Spring容器获取依赖的,它拿到的是Spring自动生成的MongoConfig实例,并非你用@Mock创建的模拟对象,所以你编写的when(mongoconfig.xxx()).thenReturn(xxx)语句自然不会生效。

二、MockMVC测试类能否同时使用@MockBean和@Mock?

可以同时使用,但要明确两者的区别和适用场景:

  • @MockBean:是Spring Boot提供的注解,会将模拟对象注册到Spring容器中,替换掉容器中原有的同类型bean,适合用来模拟Spring管理的组件(比如你的PersonActivity和PersonMapper)。
  • @Mock:是Mockito的原生注解,仅在当前测试类中创建模拟对象,不会注册到Spring容器。如果该对象需要被Spring管理的bean(比如PersonController)依赖,那么@Mock就无法满足需求,必须使用@MockBean将其注册到容器中。

解决办法

将测试类中的@Mock private MongoConfig mongoconfig;修改为@MockBean private MongoConfig mongoconfig;,这样模拟对象就会被注册到Spring容器中,替换掉原有的MongoConfig bean,PersonController就会注入你创建的模拟实例,此时你的Mockito When语句就能正常生效了。

内容的提问来源于stack exchange,提问作者java12399900

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 10:37:06