测试 API 如何使用 node.js 处理无效的 JSON 语法请求正文

Test how API handles invalid JSON syntax request body using node.js

我想测试 REST API 如何处理正文包含无效 JSON 语法(例如缺少逗号)的 POST 请求。我正在使用 node.js 编写 API 测试。我正在使用 frisby but I also tried supertest。没运气。使用以前的工具,您将请求主体作为 JavaScript 对象传递,所以这是行不通的。我还尝试将无效的 JSON 作为字符串传递,但没有任何运气,因为字符串也是有效的 JSON (下面的示例)。有什么想法吗?

frisby.create('Ensure response has right status')
    .post('http://example.com/api/books', '{"invalid"}', {json: true})
    .expectStatus(400)
    .toss();

我从来没有用过Frisby或者superagent,但是我发现这里有两个问题:

1. passing an invalid JSON from client to server using POST method.

这是不可能的,因为它很快就会在客户端本身被拒绝,并且在向服务器发出 POST 请求之前会出现错误。 (因为在使用 http 时只有字符串,客户端将自己尝试将 JSON 字符串化,它会卡在无效的 JSON 中)

2. pass an invalid JSON just as a string

示例:POST 使用 JQuery

这样的字符串
 $.post("demo_test_post.asp",
    {
        name: 'pqr:{"abc":"abc",}'    // see there is a comma at the end making JSON invalid
    },
    function(data, status){
        alert("Data: " + data + "\nStatus: " + status);
    });

这将有效地将无效的 JSON(在本例中为名称)作为 srting 传递给服务器。但这需要您使用 JSON.parse() 将字符串解析为 JSON,然后才能使用它。当你尝试时,你会得到这个:

SyntaxError: Unexpected token p at Object.parse (native) at Object.app.get.res.send.data [as handle] (/home/ubuntu/workspace/TapToBook.js:35:19) at next_layer (/home/ubuntu/workspace/node_modules/express/lib/router/route.js:103:13) at Route.dispatch (/home/ubuntu/workspace/node_modules/express/lib/router/route.js:107:5) at proto.handle.c (/home/ubuntu/workspace/node_modules/express/lib/router/index.js:195:24) at Function.proto.process_params (/home/ubuntu/workspace/node_modules/express/lib/router/index.js:251:12) at next (/home/ubuntu/workspace/node_modules/express/lib/router/index.js:189:19) at Layer.staticMiddleware [as handle] (/home/ubuntu/workspace/node_modules/express/node_modules/serve-static/index.js:55:61) at trim_prefix (/home/ubuntu/workspace/node_modules/express/lib/router/index.js:226:17) at proto.handle.c (/home/ubuntu/workspace/node_modules/express/lib/router/index.js:198:9)

因此,无论您为 Rest 使用哪个包,您都可以将无效的 JSON 作为字符串传递,但不能使用它。

我假设您的测试想要验证服务器正在处理无效 JSON(并且不会崩溃)。希望返回 400 错误请求。

由于 http 中的 POST 只是一个字符串,测试的一个选项是使用需要您提供 JSON 对象的 API。

如果您使用原始节点 http,那么您可以发送任何您想要的无效字符串:

还有流行的请求库。

https://github.com/request/request

例如,使用库,您的测试可以从文件中提取无效内容,然后 post 或放入。来自他们的文档:

fs.createReadStream('file.json').pipe(request.put('http://example.com/obj.json'))

使用 supertest 和 mocha 包,您可以通过发布无效 JSON 来测试端点,如下所示:

var request = require('supertest');

describe('Adding new book', function(){
  it('with invalid json returns a 400', function(done){
    request('http://example.com').post('/api/books')
      .send('{"invalid"}')
      .type('json')
      .expect('Content-Type', /json/)
      .expect(400)
      .end(function(err, res) {
          console.log(res.error);
          done();
      });
  });
});

这里重要的一点是 type(json)。这会将请求的 Content-Type 设置为 application/json。没有它,supertest/superagent 将默认发送字符串为 application/x-www-form-urlencoded。此外,无效的 JSON 是作为字符串而不是 JavaScript 对象提供的。

在使用npm request library的时候其实很简单的一个技巧。这是我取得的成果,并且正在发挥作用。

    describe('with invalid JSON, attempt a config api call', () => {
      let response;
      before(async () => {
        const k = "on:true";
        response = await request.put(configURL+ `/0/config/`, {
          json:k,
          headers: {
            authorization: bearer,
            "content-type": "application/json",
          }
        })
      });
      it('should return http 400 OK', () => {
        response.statusCode.should.equal(400);
      });
      it('should have error message as SyntaxError: Unexpected token in JSON body', () => {
        response.body.should.equal("SyntaxError: Unexpected token in JSON body");
      });
    });

注意:这里是无效的JSON,因为ON没有引号。这将有助于测试人员使用请求库。