Search code examples
javascriptnode.jstypescriptjestjssupertest

supertest changing url at every test


I'm new to backend development and i face a problem that i don't understand.

I set up the 1st route of my API called "health" who just return a simple message to know if my server is up.

This route looks to works as expected.

However,

when I try to test this route with the method "toMatchSnapshot" from jest API, the test is not passing because of the in the url is changing constantly.

My test file "index.test.ts":

const request = supertest.agent(app);
describe("app", () => {

  it("should return a successful response for GET /health", async () => {
    const res = await request.get("/health");
    res.header = omit(res.header, ["date"]);
    expect(res).toMatchSnapshot();
  });

});

index of the server "index.ts":

const app = express();

expressService(app);

if (require.main === module) {
  app.listen(PORT, () => {
    console.log("server started at http://localhost:" + PORT);
  });
}

export default app;

my function "expressService":

const expressService = (app: Application) => {
    app.use(cors());
    app.use(express.urlencoded({ extended: true }));
    app.use(express.json());

    app.use(api);
};

export default expressService;

My PORT variable: PORT = 3000;

-     "url": "http://127.0.0.1:49694/health",
+     "url": "http://127.0.0.1:52568/health",

this is where the test is failing.

Thank you for your answers.


Solution

  • The doc of supertest says:

    You may pass an http.Server, or a Function to request() - if the server is not already listening for connections then it is bound to an ephemeral port for you so there is no need to keep track of ports.

    You need to pass a Node.js http.Server object to supertest.agent(), then you can use the specific PORT for testing.

    Here is the solution:

    index.ts:

    import express from 'express';
    import expressService from './expressService';
    import http from 'http';
    
    const app = express();
    const PORT = process.env.PORT || 3000;
    
    expressService(app);
    
    function createHttpServer() {
      const httpServer: http.Server = app.listen(PORT, () => {
        console.log('server started at http://localhost:' + PORT);
      });
    
      return httpServer;
    }
    
    if (require.main === module) {
      createHttpServer();
    }
    
    export default createHttpServer;
    

    expressService.ts:

    import { Application } from 'express-serve-static-core';
    import express, { Router } from 'express';
    import cors from 'cors';
    
    const expressService = (app: Application) => {
      app.use(cors());
      app.use(express.urlencoded({ extended: true }));
      app.use(express.json());
    
      const api = Router();
    
      api.get('/health', (req, res) => {
        res.sendStatus(200);
      });
    
      app.use(api);
    };
    
    export default expressService;
    

    index.spec.ts:

    import createHttpServer from './';
    import { agent } from 'supertest';
    import { omit } from 'lodash';
    
    const httpServer = createHttpServer();
    const request = agent(httpServer);
    
    afterAll(done => {
      httpServer.close(done);
    });
    
    describe('app', () => {
      it('should return a successful response for GET /health', async () => {
        const res = await request.get('/health');
        res.header = omit(res.header, ['date']);
        expect(res).toMatchSnapshot();
      });
    });
    

    Unit test result:

     PASS  src/stackoverflow/57409561/index.spec.ts (7.853s)
      app
        ✓ should return a successful response for GET /health (61ms)
    
      console.log src/stackoverflow/57409561/index.ts:12
        server started at http://localhost:3000
    
    Test Suites: 1 passed, 1 total
    Tests:       1 passed, 1 total
    Snapshots:   1 passed, 1 total
    Time:        8.66s
    

    Snapshot:

    // Jest Snapshot v1
    
    exports[`app should return a successful response for GET /health 1`] = `
    Object {
      "header": Object {
        "access-control-allow-origin": "*",
        "connection": "close",
        "content-length": "2",
        "content-type": "text/plain; charset=utf-8",
        "etag": "W/\\"2-nOO9QiTIwXgNtWtBJezz8kv3SLc\\"",
        "x-powered-by": "Express",
      },
      "req": Object {
        "data": undefined,
        "headers": Object {
          "user-agent": "node-superagent/3.8.3",
        },
        "method": "GET",
        "url": "http://127.0.0.1:3000/health",
      },
      "status": 200,
      "text": "OK",
    }
    `;
    

    Here is the completed demo: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/57409561