Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I would like to test how an REST API handles a POST request that has a body with invalid JSON syntax, for example a missing comma. I'm using node.js to write the API tests. I'm using frisby but I also tried supertest. No luck. With the previous tools, you pass the request body as a JavaScript object, so it's no go. I tried also to pass the invalid JSON as a string without any luck, since a string is also valid JSON (example below). Any ideas?

frisby.create('Ensure response has right status')
    .post('http://example.com/api/books', '{"invalid"}', {json: true})
    .expectStatus(400)
    .toss();
like image 475
alefteris Avatar asked Feb 02 '15 20:02

alefteris


3 Answers

Using the supertest and mocha packages, you can test an endpoint by posting the invalid JSON like this:

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();
      });
  });
});

The important bit here is type(json). This will set the Content-Type of the request to application/json. With out it, supertest/superagent will default to sending strings as application/x-www-form-urlencoded. Also the invalid JSON is provided as a string and not as a JavaScript object.

like image 70
alefteris Avatar answered Oct 03 '22 11:10

alefteris


I have never used Frisby or superagent, but I find there are two questions here:

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

Which is not possible because , it will be soon rejected at the client side itself, and you will get error before making a POST request to the server. (because as there are only strings while working with http, the client will itself try to stringify the JSON where it will get stuck with invalid JSON)

2. pass an invalid JSON just as a string

example: POST a string like this using 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);
    });

This will effectively pass the invalid JSON (name in this case) to the server as a srting. But this will require you to parse the string to JSON using JSON.parse() before you can use it. And when you try that you get this:

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)

So whichever packages you use for Rest, you can pass invalid JSON as a string, but not use it.

like image 37
Naeem Shaikh Avatar answered Oct 03 '22 11:10

Naeem Shaikh


I assume your test want's to validate the server is handling invalid JSON (and doesn't crash). Hopefully returning a 400 bad request.

Since a POST in http is just a string, an option for the test is to use an API that requires you to supply a JSON object.

If you use raw node http, then you can send whatever invalid string you want:

How to make an HTTP POST request in node.js?

There's also the popular request library.

https://github.com/request/request

For example, with the library, your test could pick up the invalid content from a file and post or put. From their docs:

fs.createReadStream('file.json').pipe(request.put('http://example.com/obj.json'))
like image 29
bryanmac Avatar answered Oct 03 '22 11:10

bryanmac