如何为父函数内部调用的特定API请求函数设置stub开展测试
单独stub子函数的实现方案
前置调整:抽离可mock的请求函数
首先要把request1、request2等独立的外部请求函数抽成单独的模块导出,只有导出的函数才能被stub工具捕获替换:
// requests.js 抽离后的公共请求模块 import request from 'request-promise' export const request1 = async (data) => request({uri: "service1.com/get", method: "GET"}) export const request2 = async (data) => request({uri: "service2.com/get", method: "GET"}) export const request3 = async (data) => request({uri: "service3.com/get", method: "GET"}) export const request4 = async (data) => request({uri: "service4.com/get", method: "GET"})
调整原有业务代码的导入逻辑:
import {request1, request2, request3, request4} from './requests.js' export const apiRequests = async (data) => { const req1 = await request1(data); const req2 = await request2(data); if (req1 && req2) { const req3 = await request3(data); const req4 = await request4(data); return "Second return" } return "First return" }
编写测试用例(基于Loopback testlab内置能力)
Loopback testlab内置了stub能力,无需额外引入第三方包,你可以单独为每个请求函数设置自定义返回值:
// 测试文件 import {stub, expect} from '@loopback/testlab'; import {apiRequests} from './你的业务代码文件路径.js'; import * as requestServices from './requests.js'; // 测试返回First return的分支 it('返回First return当request1返回false时', async () => { // 单独stub request1返回false,不影响其他函数逻辑 const stubReq1 = stub(requestServices, 'request1').resolves(false); // 按需设置request2的返回值 const stubReq2 = stub(requestServices, 'request2').resolves(true); const result = await apiRequests({test: '测试数据'}); expect(result).to.equal('First return'); // 测试结束恢复原函数,避免影响其他用例 stubReq1.restore(); stubReq2.restore(); }) // 测试返回Second return的分支 it('返回Second return当request1和request2都返回true时', async () => { const stubReq1 = stub(requestServices, 'request1').resolves(true); const stubReq2 = stub(requestServices, 'request2').resolves(true); // 也可单独stub后续的req3、req4返回值 const stubReq3 = stub(requestServices, 'request3').resolves('mock返回值3'); const stubReq4 = stub(requestServices, 'request4').resolves('mock返回值4'); const result = await apiRequests({test: '测试数据'}); expect(result).to.equal('Second return'); // 批量恢复所有stub [stubReq1, stubReq2, stubReq3, stubReq4].forEach(s => s.restore()); })
核心逻辑说明
- stub方法会临时替换模块导出的函数引用,父函数内部调用的对应子函数会自动使用你stub后的逻辑,无需修改原有业务代码
- 每个stub可以独立设置返回值,互相不影响,你可以按照测试分支的需要,单独控制req1返回false、req2返回true等任意组合
- 测试用例执行结束后必须调用
restore()方法恢复原函数,避免对其他测试用例产生干扰
其他常用场景
如果要模拟请求抛出异常的场景,把.resolves(xxx)替换为.rejects(new Error('自定义错误信息'))即可覆盖异常处理分支。
内容的提问来源于stack exchange,提问作者RoboKy
相关产品推荐
相关产品推荐

