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语句无法生效,想请教两个问题:
- 该失效问题的原因是什么?
- 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
相关产品推荐
相关产品推荐

