我正在尝试使用@WebMvcTest
测试我的Rest Controller的Rest合约,例如:
@RunWith(SpringRunner.class)
@WebMvcTest(MyController.class)
class MyControllerTest {
我正在测试的方法只使用MyFirstService,但在类中还有另外两个服务使用的另外两个服务(MySecondService和MyThirdService)。
问题在于使用@MockBean
。在决赛中,测试类似乎是这样的:
@RunWith(SpringRunner.class)
@WebMvcTest(MyController.class)
class MyControllerTest {
@MockBean
private MyFirstService s1; // internal method mocked for the test
@MockBean
private MySecondService s2; //never used
@MockBean
private MyThirdService s3; //never used
...
@Test
public void testMethod() [
// mock s1
// calls rest controller method
MvcResult mvcResult = mvc.perform(post("/products")
.header("Content-Type", "application/json")
.content(json))
.andExpect(status().isCreated())
.andReturn();
}
}
我认为这个解决方案并不优雅......声明的s2和s3似乎不会从读取代码的人那里使用。并且MyController中注入的每个服务都需要@MockBean
。
所以,我有两个问题:
@MockBean
?@MockBean
?答案 0 :(得分:2)
第一个问题:
有没有办法在Spring MVC测试中不使用@MockBean?
@WebMvcTest
允许在Spring上下文中仅配置MVC bean
作为优势,它可以隔离测试并使其执行速度更快
作为缺点,它需要为测试控制器的依赖性提供模拟,即使在测试方法中不需要它们。
Spring文档确认:
41.3.7 Auto-configured Spring MVC tests
@WebMvcTest通常仅限于一个控制器并在其中使用 与@MockBean组合以提供模拟实现 需要合作者。
所以在你的情况下,你没有选择权。
第二个问题:
有没有更好的方法来做同样的事情,即使使用@MockBean?
我认为您可以使用@MockBean
为您希望在测试中模拟特定内容的字段生成更好的代码,并根据所测试的控制器将@MockBeans
用于其他bean类。
没有经过测试,但您可以尝试:
@RunWith(SpringRunner.class)
@WebMvcTest(MyController.class)
@MockBeans({ @MockBean(MySecondService.class),
@MockBean(MyThirdService.class)
}) // technical mocks for the dependencies resolution
class MyControllerTest {
@MockBean
private MyFirstService s1;
@Test
public void testMethod() [
// mock s1
// calls rest controller method
MvcResult mvcResult = mvc.perform(post("/products")
.header("Content-Type", "application/json")
.content(json))
.andExpect(status().isCreated())
.andReturn();
}
}