Nock+TS完全指南:类型安全Mock实战
【免费下载链接】nock 项目地址: https://gitcode.com/gh_mirrors/noc/nock
你还在为API Mock类型不匹配抓狂?接口联调时TypeScript报错让测试卡壳?本文将带你用Nock+TS构建类型安全的Mock系统,从类型定义到实战案例,彻底解决前端Mock的类型痛点。读完你将掌握:Nock类型系统核心模块、3种类型安全Mock模式、TypeScript测试最佳实践。
Nock类型系统核心架构
Nock通过types/index.d.ts提供完整类型定义,核心类型构成三层架构:
// 核心类型关系示意
export declare function nock(basePath: string | RegExp | Url | URL, options?: nock.Options): nock.Scope;
declare namespace nock {
interface Scope extends NodeJS.EventEmitter { /* 拦截器管理 */ }
interface Interceptor { /* 请求匹配规则 */ }
type ReplyFnResult = readonly [StatusCode] | readonly [StatusCode, ReplyBody] | readonly [StatusCode, ReplyBody, ReplyHeaders];
}
核心类型解析
Scope接口:作为Mock作用域的入口点,管理一组相关拦截器。通过链式调用定义多个请求匹配规则:
const scope = nock('https://api.example.com')
.get('/users')
.reply(200, users)
.post('/users')
.reply(201, newUser);
Interceptor接口:定义单个请求的匹配规则和应答策略,支持多种匹配模式:
// 精确匹配
nock('http://example.test').get('/users/1').reply(200)
// 正则匹配
nock('http://example.test').get(/\/users\/\d+/).reply(200)
// 函数匹配
nock('http://example.test').get(uri => uri.startsWith('/users')).reply(200)
ReplyFnResult类型:确保应答格式的类型安全,支持三种返回形式:
[statusCode][statusCode, body][statusCode, body, headers]
类型安全Mock的三种实现模式
1. 基础类型匹配模式
利用TypeScript类型推断,确保请求参数与应答格式符合预期:
// 正确示例:完整类型定义
interface User {
id: number;
name: string;
}
const scope = nock<Scope>('https://api.example.com')
.get<User>('/users/1') // 指定返回类型
.reply(200, { id: 1, name: 'John' }); // 类型检查通过
// 错误示例:类型不匹配
scope.get<User>('/users/1')
.reply(200, { userId: 1, userName: 'John' }); // TS编译错误:属性不匹配
2. 请求体类型验证模式
通过泛型约束确保请求体结构正确:
interface CreateUserRequest {
name: string;
email: string;
}
nock('https://api.example.com')
.post<CreateUserRequest>('/users', (body) => {
// 请求体类型自动推断为CreateUserRequest
return body.email.includes('@'); // 额外业务验证
})
.reply(201, (uri, body) => ({
id: 1,
...body // 类型安全的请求体透传
}));
3. 高级应答函数模式
使用异步函数处理复杂应答逻辑,同时保持类型安全:
nock('https://api.example.com')
.get('/data')
.reply<DataResponse>(async (uri) => {
const data = await fetchMockData(); // 模拟异步数据获取
return [200, data]; // 类型检查确保返回[number, DataResponse]
});
类型测试实战案例
types/tests.ts提供了200+类型测试用例,覆盖各种边界场景:
典型测试用例解析
// 测试查询参数匹配
nock('http://example.test')
.get('/users')
.query({ name: 'pedro', surname: 'teixeira' }) // 精确匹配
.reply(200, { results: [{ id: 'pgte' }] });
// 测试请求头匹配
nock('http://example.test', {
reqheaders: {
authorization: 'Basic Auth',
'X-My-Header': /Awesome/i
}
})
.get('/')
.reply(200);
// 测试延迟应答
nock('http://example.test')
.get('/')
.delay(2000) // 延迟2秒
.delayBody(1000) // 响应体延迟1秒
.reply(200, 'Delayed response');
测试覆盖率分析
Nock的TypeScript类型测试覆盖:
- ✅ 所有HTTP方法(GET/POST/PUT/DELETE等)
- ✅ 请求参数/查询/头信息匹配
- ✅ 应答状态码/体/头信息组合
- ✅ 异常处理与错误模拟
- ✅ 延迟与异步场景
最佳实践与避坑指南
类型定义扩展技巧
自定义类型扩展满足特定业务需求:
// 扩展Nock类型定义
declare module 'nock' {
interface Scope {
// 添加自定义方法
log(message: string): this;
}
}
// 使用扩展方法
nock('https://api.example.com')
.log(console.log) // 自定义日志方法
.get('/')
.reply(200);
常见类型问题解决方案
- 问题:复杂嵌套对象类型不匹配 方案:使用类型断言与类型守卫结合
// 类型守卫函数
function isUserResponse(data: unknown): data is UserResponse {
return typeof data === 'object' && data !== null && 'id' in data;
}
nock('https://api.example.com')
.get('/user')
.reply(200, (uri, body) => {
const response = fetchData();
if (!isUserResponse(response)) {
throw new Error('Invalid response type');
}
return response;
});
- 问题:第三方库类型冲突 方案:使用module augmentation隔离类型
// 隔离第三方类型冲突
declare module 'nock' {
namespace Nock {
interface Options {
// 扩展自定义选项
myCustomOption?: boolean;
}
}
}
总结与进阶方向
Nock的TypeScript类型系统通过types/index.d.ts实现了完整的类型覆盖,结合本文介绍的三种模式,可构建从简单到复杂的类型安全Mock系统。建议进一步学习:
- 深入阅读Nock官方文档了解更多高级特性
- 研究examples目录中的实战案例
- 参与类型定义改进:CONTRIBUTING.md
掌握Nock+TS的类型安全Mock技术,让你的API测试从"运行时发现错误"升级为"编译时预防错误",大幅提升前端工程质量与开发效率。
点赞+收藏本文,关注作者获取更多TypeScript工程化实践指南!下期预告:《Nock与React组件测试深度整合》
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



