当前位置: 首页 > 知识库问答 >
问题:

Sinon JS存根HTTP请求

晏华奥
2023-03-14

我需要为一个endpoint创建一个单元测试,这个endpoint将向某个API发出HTTP请求,并发送回包含HTTP请求结果的响应,

我使用请求promise链接在这里节点包,你可以看到下面的代码

router.get("/url", function(req, res){
  let options = { url: "http//some-api-en-point", 
    method: "GET",
    resolveWithFullResponse: true
  };
  rp(options)
  .then(function(response) {
    if(response.statusCode == 200){
      res.send({"data":response.data})
    } else {
      res.status(404).json("data":"NOT FOUND");
    }
  })
  .catch(err => () => {
    res.send(err);
  })
});

来自 http//某些 API 的预计正文(响应数据)是:

{ 
  "id": "3f3e2b23e96c5250441d4be2340010ed",
  "email": "let@example.com",
  "status": "1"
}

我使用摩卡、柴和西农来运行单元测试,你可以在下面看到上述功能的单元测试案例:

describe('TEST: /URL', () => {
  it('it should return Status 200', (done) => { 
    chai.request(app)
      .get('/url')
      .end((err, res) => {
        sinon.stub(rp, 'Request').resolves({statusCode:200}); 
        expect(res).to.have.status(200);
        done();
      });
  });
});

当我运行npm测试时,此集成测试总是失败,需要找出如何正确地存根。

共有1个答案

李经国
2023-03-14

以下是集成测试:

< code>server.ts:

import express from 'express';
import { Router } from 'express';
import rp from 'request-promise';

const app = express();
const router = Router();

router.get('/url', function(req, res) {
  let options = { url: 'http//some-api-en-point', method: 'GET', resolveWithFullResponse: true };
  rp(options)
    .then(function(response) {
      if (response.statusCode == 200) {
        res.send({ data: response.data });
      } else {
        res.status(404).json({ data: 'NOT FOUND' });
      }
    })
    .catch(err => {
      res.send(err);
    });
});

app.use(router);

export { app };

服务器规范:

import chai, { expect } from 'chai';
import chaiHttp from 'chai-http';
import sinon from 'sinon';
import proxyquire from 'proxyquire';
chai.use(chaiHttp);

const mData = {
  id: '3f3e2b23e96c5250441d4be2340010ed',
  email: 'let@example.com',
  status: '1'
};

describe('Test: /URL', () => {
  it('should return Status 200', done => {
    const mResponse = { statusCode: 200, data: mData };
    const mRp = sinon.stub().resolves(mResponse);
    const { app } = proxyquire('./server', {
      'request-promise': mRp
    });

    chai
      .request(app)
      .get('/url')
      .end((err, res) => {
        expect(err).to.be.null;
        expect(res).to.have.status(200);
        expect(mRp.calledWith({ url: 'http//some-api-en-point', method: 'GET', resolveWithFullResponse: true }));
        done();
      });
  });

  it('should return status 404', done => {
    const mResponse = { statusCode: 500, data: mData };
    const mRp = sinon.stub().resolves(mResponse);
    const { app } = proxyquire('./server', {
      'request-promise': mRp
    });

    chai
      .request(app)
      .get('/url')
      .end((err, res) => {
        expect(err).to.be.null;
        expect(res).to.have.status(404);
        expect(res.body).to.deep.equal({ data: 'NOT FOUND' });
        expect(mRp.calledWith({ url: 'http//some-api-en-point', method: 'GET', resolveWithFullResponse: true }));
        done();
      });
  });

  it('should send error', done => {
    const mError = 'network error';
    const mRp = sinon.stub().rejects(mError);
    const { app } = proxyquire('./server', {
      'request-promise': mRp
    });

    chai
      .request(app)
      .get('/url')
      .end((err, res) => {
        expect(err).to.be.null;
        expect(res.body).to.deep.equal({ name: 'network error' });
        expect(res).to.have.status(200);
        expect(mRp.calledWith({ url: 'http//some-api-en-point', method: 'GET', resolveWithFullResponse: true }));
        done();
      });
  });
});

100% 覆盖率的单元测试结果:

  Test: /URL
    ✓ should return Status 200 (1558ms)
    ✓ should return status 404 (116ms)
    ✓ should send error (90ms)


  3 passing (2s)

----------------|----------|----------|----------|----------|-------------------|
File            |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
----------------|----------|----------|----------|----------|-------------------|
All files       |      100 |      100 |      100 |      100 |                   |
 server.spec.ts |      100 |      100 |      100 |      100 |                   |
 server.ts      |      100 |      100 |      100 |      100 |                   |
----------------|----------|----------|----------|----------|-------------------|

源代码:https://github.com/mrdulin/mocha-chai-sinon-codelab/tree/master/src/stackoverflow/57176000

 类似资料:
  • Similar to the section on testing Backbone.js apps using the Jasmine BDD framework, we’re nearly ready to take what we’ve learned and write a number of QUnit tests for our Todo application. Before we

  • SinonJS 是一个独立的 JavaScript 测试间谍,没有依赖任何单元测试框架工程。

  • 我使用Jmeter进行API测试,使用各种http请求和各种采样器来验证它们。现在,我正在为另一个http请求编写测试。在此测试中,步骤如下: < li >发出http请求。处理响应。 < li >使用xpath xtractor,我提取响应并将URL存储在另一个变量(store_url)中。 < li >如果变量有URL,请重复步骤1。这个循环必须重复,直到没有值存储在(store_URL)中。

  • 我有一个android应用程序,其中使用了第三方jar。Http请求是在应用程序运行时从第三方jar发送到服务器的。我需要捕获从第三方JAR发送的HTTP请求。我想知道是否有一个简单的方法来实现非根设备 启动:我试过下载“ProxyDroid”,但它需要根手机我也试过用“Shark Reader”下载“Shark for Root”,它也需要根设备我试过很多其他应用程序,它们可以捕获完整的请求,但

  • 我正在尝试模拟相同的请求URL(多次),根据JSON Body内容有不同的响应。 我的请求JSON是动态构建的,所以我不能在Mock上静态使用< code>equalToJson函数。 我有相同的JSON,如下所示: < code>wireMockServer存根的最佳方法是什么? 我正在尝试这样的东西 我在留档中没有找到这样的样品。谢谢!

  • 主要内容:HTTP请求完整格式HTTP请求完整格式 HTTP请求由3部分组成(请求行+请求头+请求体): 下面是一个实际的请求示例: ①是请求方法,HTTP/1.1 定义的请求方法有8种:GET、POST、PUT、DELETE、PATCH、HEAD、OPTIONS、TRACE,最常的两种GET和POST,如果是RESTful接口的话一般会用到GET、POST、DELETE、PUT。 ②为请求对应的URL地址,它和报文头的Hos