mocha.jssupertestvows

mocha: can't use one request for mutlple `it` test


const request = require('supertest');

const server = request('http://localhost:9001');

describe('Get /static/component-list.json', function() {
    const api = server.get('/static/component-list.json');

    it('should response a json', function(done) {
        api.expect('Content-Type', /json/, done);
    });
    it('200', function(done) {
        api.expect(200, done); // This will failed
        // server.get('/static/component-list.json').expect(200, done); // This will successed
    });
});

when reuse api in the second test case, mocha will raise a Error:

The result of mocha test/api command:

mocha error

How can I request the url once and use in multiple it case.


Solution

  • Solution

    You have to create a new request for each test (each it) that you want to run. You cannot reuse the same request for multiple tests. So

    describe('Get /static/component-list.json', function() {
        let api;
    
        beforeEach(() => {
            api = server.get('/static/component-list.json');
        });
    

    Or if you want to reduce the number of requests made, then combine all your checks on the request into a single Mocha test.

    Explanation

    If you look at the code of supertest, you'll see that when you call an expect method with a callback, expect calls automatically calls end. So this:

    api.expect('Content-Type', /json/, done);
    

    is equivalent to this:

    api.expect('Content-Type', /json/).end(done);
    

    The end method is provided by superagent, which is what supertest uses to perform requests. The end method is what kicks off the request. It means you are done setting up the request and want to fire it off now.

    The end method calls the request method, which is tasked with using Node's networking machinery to produce a Node request object that is used to perform the network operation. The problem is that request caches the Node request is produces but this Node request object is not reusable. So ultimately, a superagent or supertest request cannot be ended twice. You have to reissue the request for each test.

    (You could manually flush the cached object between tests by doing api.req = undefined. But I strongly advise against this. For one thing, whatever optimization you might think you'd get is minimal because the network request still has to be made anew. Secondly, this amounts to messing with superagent's internals. It may break with a future release. Third, there may be other variables that hold state that might need to be reset together with req.)