前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >使用 Nock 来模拟 http 请求响应

使用 Nock 来模拟 http 请求响应

作者头像
IMWeb前端团队
发布2019-12-03 17:00:03
1.9K0
发布2019-12-03 17:00:03
举报
文章被收录于专栏:IMWeb前端团队

本文作者:IMWeb zzbozheng 原文出处:IMWeb社区 未经同意,禁止转载

nock 是前端常用来模拟http请求响应的工具,它基于nodejs的原生http模块,并且他可以让我们写一些轻逻辑的代码,我们先看一个简单的例子:

代码语言:javascript
复制
nock('http://www.example.com')
  .post('/login', 'username=pgte&password=123456')
  .reply(200, { id: '123ABC' });

fetchUser('pgte', '123456');

上面的例子中fetchUser会发出一个post请求到example.com/login. Nock将会拦截这个请求并立即返回你预先定义好的响应。

当我第一次开始使用Nock时,我急切地开始使用它进行单元测试。 然而,我很快就感觉到我花了更多时间编写Nocks而不是实际测试业务逻辑。 对此的一个解决方案是将您的请求代码与业务逻辑分开。 我们来看一些例子吧:

代码语言:javascript
复制
async function getUser(id) {
  const response = await fetch(`/api/users/${id}`);

  // User does not exist
  if (response.status === 404) return null;
  // Some other error occurred
  if (response.status > 400) {
    throw new Error(`Unable to fetch user #${id}`);
  }

  const { firstName, lastName } = await response.json();
  return {
    firstName,
    lastName,
    fullName: `${firstName} ${lastName}`
  };
}

/api/users/<用户ID>发送请求,当处理完响应结果返回一个 firstName 和 lastName 的对象。 此功能的测试代码可能如下所示:

代码语言:javascript
复制
it('should properly decorate the fullName', async () => {
  nock('http://localhost')
    .get('/api/users/123')
    .reply(200, { firstName: 'John', lastName: 'Doe });

  const user = await getUser(123);
  expect(user).toEqual({
    firstName: 'John',
    lastName: 'Doe,
    fullName: 'John Doe'
  });
});  

it('should return null if the user does not exist', async () => {
  nock('http://localhost')
    .get('/api/users/1337')
    .reply(404);

  const user = await getUser(1337);
  expect(user).toBe(null);
});  

it('should return null when an error occurs', async () => {
  nock('http://localhost')
    .get('/api/users/42')
    .reply(404);

  const userPromise = getUser(42);
  expect(userPromise).rejects.toThrow('Unable to fetch user #42');
});

上面的测试代码主要分为两部分:

  • 发送和处理HTTP请求
  • 业务逻辑
代码语言:javascript
复制
// api.js
export async function getUserFromApi(id) {
  const response = await fetch(`/api/users/${id}`);

  // User does not exist
  if (response.status === 404) return null;
  // Some other error occurred
  if (response.status > 400) {
    throw new Error(`Unable to fetch user #${id}`);
  }
  return response.json();
}  

// user.js
import { getUserFromApi } from './api';  

async function getUserWithFullName(id) {
  const user = await getUserFromApi(id);
  if (!user) return user;
  const { firstName, lastName } = user;
  return {
    firstName,
    lastName,
    fullName: `${firstName} ${lastName}`
  };
}

使用正则匹配hostname

代码语言:javascript
复制
var scope = nock(/\.qq\.com$/)
    .get('/resource')
    .reply(200, 'domain regex matched');

path 可以通过正则或过滤函数

代码语言:javascript
复制
var scope = nock('http://www.example.com')
    .get(/source$/)
    .reply(200, 'path using regex matched');
代码语言:javascript
复制
var scope = nock('http://www.example.com')
    .get(function(uri) {
      return uri.indexOf('cats') >= 0;
    })
    .reply(200, 'path using function matched');

请求响应可以使用回调函数

代码语言:javascript
复制
var scope = nock('http://www.google.com')
   .filteringRequestBody(/.*/, '*')
   .post('/echo', '*')
   .reply(201, function(uri, requestBody) {
     return requestBody;
   });
代码语言:javascript
复制
var scope = nock('http://www.google.com')
   .filteringRequestBody(/.*/, '*')
   .post('/echo', '*')
   .reply(201, function(uri, requestBody, cb) {
     fs.readFile('cat-poems.txt' , cb); // Error-first callback
   });

最后

你也可以使用您选择的模拟库来模拟我们自己的API包装器,而不是使用Nock来模拟HTTP请求。 我更喜欢Jest,但这种模式并不依赖于任何特定的模拟库。

代码语言:javascript
复制
import { getUserFromApi } from './api';
jest.mock('./api');  

it('should properly decorate the fullName', async () => {
  getUserFromApi.mockResolvedValueOnce(
    { firstName: 'John', lastName: 'Doe }
  );

  const user = await getUser(123);
  expect(user).toEqual({
    firstName: 'John',
    lastName: 'Doe,
    fullName: 'John Doe'
  });
});  

it('should return null if the user does not exist', async () => {
  getUserFromApi.mockResolvedValueOnce(null);

  const user = await getUser(1337);
  expect(user).toBe(null);
});

这样的测试看起来更简洁。 所有HTTP开销现在都包含在API模块中。 我们已经最小化地完成了HTTP传输,最大限度地减少了使用 Nock 来测度 。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018-07-06 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 使用正则匹配hostname
  • path 可以通过正则或过滤函数
  • 请求响应可以使用回调函数
  • 最后
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档