springboot 中 Mock 三方接口测试service类
1、背景
在 业务逻辑中间需要调用 三方部门的接口,但三方接口还在开发中,只提供了 接口名称,自己业务已经开发完成,所以需要Mock 掉单三方的 调用。
2、 使用Mock进行测试
需求是 要 部分mock的形式(只mock 三方的接口),其他 bean 使用真实的实例。
使用 @SpringbootTest, 启动容器测试。
调用方法1相关的部分链路
XxxInfoService->XxxInfoService: 测试目标方法类
XxxInfoService->XxxApiService: 三方接口
XxxInfoService->XxxInvokeService: 操作db
XxxInfoService->....: 其他操作
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class MockTest {
/**
* 其他 未 定义 @Mock 的类,通过 spring注入到 IOC中
*/
@Autowired
@InjectMocks
private XxxInfoService xxxInfoService;
//需要 mock 执行的 类
@Mock
private XxxApiService xxxApiService;
@Before
public void init() {
//Mock IOC
MockitoAnnotations.initMocks(this);
}
@Test
public void test() throws IOException {
//同@Mock 二选一
// xxxApiService = Mockito.mock(XxxApiService.class);
XxxResponseBase responseBase = new XxxResponseBase();
responseBase.setCode(0);
//Mock 三方接口的 result
Mockito.when(xxxApiService.feedbackOrderSubmit(any()))
.thenReturn(responseBase);
Config config = new Config();
config.setOrderId("123");
xxxInfoService.notifyOss(config);
}
}
结果:执行成功,并且 db中插入 记录
调用方法2的 部分调用链路,所有数据的获取都需要mock
XxxInfoService->XxxInfoService: 测试目标方法类
XxxInfoService->XxxApiService: 三方接口 mock
XxxInfoService->XxxService: 查询 mock
XxxInfoService->aaaService: 三方接口 mock
XxxInfoService->XxxInvokeService: 操作db
XxxInfoService->....: 其他操作
public void test_syncData() {
String orderId="1";
List<InfoDO> successServers= Arrays.asList(new InfoDO());
InfoConfig infoConfig= new InfoConfig();
infoConfig.setBasicConfig(new BasicConfig());
infoConfig.getBasicConfig().setOrderId(orderId);
infoConfig.getBasicConfig().setWid("1");
infoConfig.getBasicConfig().setCid(1);
infoConfig.getBasicConfig().setServiceId(2);
infoConfig.getBasicConfig().setIpServiceId(3);
infoConfig.getBasicConfig().setBwServiceId(4);
XxxOrderDO order = new XxxOrderDO();
order.setDesc("test");
Mockito.when(orderService.getOrder(any())).thenReturn(order);
ServerInfo serverInfo = new ServerInfo();
serverInfo.setDetail(new XxxDetailResponse.Detail());
serverInfo.getDetail().setInfo(new XxxDetailResponse.Info());
serverInfo.getDetail().getInfo().setOsName("os");
serverInfo.getDetail().getInfo().setLcUuid("uuid");
serverInfo.getDetail().getInfo().setLabel("lable");
serverInfo.getDetail().getInfo().setSn("sn");
serverInfo.getDetail().getInfo().setOrderId(123);
serverInfo.getDetail().getInfo().setZoneName("Lax");
serverInfo.getDetail().getInfo().setName("pre");
serverInfo.getDetail().getInfo().setStartTime("2020-12-12 10:12:12");
serverInfo.getDetail().getInfo().setOwnWanIp("10.10.10.10");
serverInfo.getDetail().getInfo().setWanLanId(0);
serverInfo.getDetail().getInfo().setWanSwIfname("ddff");
serverInfo.getDetail().getInfo().setSnmpIp("10.22.22.22");
Mockito.when(aaaService.serverDetail(any(),any())).thenReturn(serverInfo);
xxxResponseBase responseBase = new xxxResponseBase();
responseBase.setCode(0);
Mockito.when(xxxApiService.synaaaData(any())).thenReturn(responseBase);
//场景1
xxxInfoService.syncData(successServers, infoConfig, true,orderId);
// 场景 2
serverInfo.getDetail().getInfo().setWanLanId(1);
GetVpcVlanResponse response = new GetVpcVlanResponse();
response.setData(new GetVpcVlanResponse.Data());
response.getData().setPortName("port--");
response.getData().setSnmpIP("122--");
GetVpcVlanResponse.Server server = new GetVpcVlanResponse.Server();
server.setLcuuid("111");
response.getData().setServers(Arrays.asList(server));
response.setSuccess(true);
Mockito.when(aaaService.getVpc(any(),any())).thenReturn(response);
ServerDetailListResponse serverDetailListResponse = new ServerDetailListResponse();
XxxDetailResponse.Detail detail = new XxxDetailResponse.Detail();
XxxDetailResponse.Info info = new XxxDetailResponse.Info();
info.setSnmpIp("33");
info.setWanSwIfname("info-33");
detail.setInfo(info);
serverDetailListResponse.setDetail(Arrays.asList(detail));
serverDetailListResponse.setSuccess(true);
Mockito.when(aaaService.serverDetails(any(),any())).thenReturn(serverDetailListResponse);
xxxInfoService.syncData(successServers, infoConfig, true,orderId);
//场景3 faied
xxxInfoService.syncData(new ArrayList<>(), infoConfig, true,orderId);
}
3、在查询资料过程中,看到
大概浏览了下下 Mock文档, 看了一些基本的操作, 还在 Testing in Spring Boot 中发现,并不需要启动整个环境进行测试,在上面的测试中,自己也有感觉,这是用到了几个类,启动整个环境太重了。 可以通过不同的注解 分层测试。有兴趣大家可以自己看看。
-
Integration Testing With@DataJpaTest
-
Mocking With @MockBean
- 结合 @TestConfiguration 加载 Bean
-
Unit Testing With @WebMvcTest
总结
1、Mockito 框架功能很多,我只差了 我要用到的部分,
2、为了能更好的分层测试,在代码编写过程中注意 分层。
3、操作数据多的情况下,工作量还是很大的。
4、对静态类的Mock 需要使用PowerMock。
5、typora 中画图功能强大。
在 mock 使用2中有了 更清晰的了解.