santiq / bulletproof-nodejs

Implementation of a bulletproof node.js API 🛡️
https://softwareontheroad.com/ideal-nodejs-project-structure/
MIT License
5.51k stars 1.15k forks source link

Issue with Jest and Supertest #66

Open lennodev opened 4 years ago

lennodev commented 4 years ago

I am trying to use Jest and Supertest to test my endpoint.

I added server variable and module.export = server in app.ts, so supertest can retrieve the server to perform testing. However, I found the server is return before the dependency injection is ready. which cause an error TypeError: Cannot read property 'address' of null.

Could you please provide a sample of how to adopt jest and supertest with your design?

leonpahole commented 4 years ago

Hello,

I have the same issue as you. I solved it by importing and running loaders in beforeAll clause instead of importing express app from app.js. I don't know how good of a solution this is, and I would appreciate some feedback from an experienced tester. I am using javascript code for tests, and still looking into how to support typescript. Here is an example:

const request = require('supertest');
const express = require('express');

let expressApp = null;

beforeAll(async (done)=> {
    expressApp = express();
    await require('../dist/loaders').default({ expressApp })
    done();
});

describe('Endpoints availability', () => {

  it('should return 404', async () => {
    const res = await request(expressApp)
      .get('/api/nonexisting')
      .send()
    expect(res.statusCode).toEqual(404)
  })
})
canlopes commented 4 years ago

@leonpahole maybe something like this?

import { default as request } from 'supertest'
import express from 'express'
import loaders from '../loaders'

const app = express()

beforeAll(async (done) => {
  await loaders({ expressApp: app })
  done()
})

describe('Endpoints availability', () => {
  it('should return 404', async () => {
    const res = await request(app).get('/api/nonexisting').send()
    expect(res.status).toEqual(404)
  })
})
shanshaji commented 3 years ago

I am not sure whether this is the right way, but I created one index.test.js and called the other tests with app instance from there. I don't want thebeforeAll in all test.js files.

const request = require('supertest');
const express = require('express');
const { setupDatabase } = require('../fixtures/db');
const loaders = require('../../src/loaders');
const conversationTests = require("./user/conversationTests.js")
const userCrudTests = require("./user/userCrud.js")

const app = express();

beforeAll(async (done) => {
    await loaders({ expressApp: app });
    done();
});
beforeEach(setupDatabase);

test("Should connect app", async () => {
    await request(app)
      .get('/status')
      .send()
      .expect(200);
})

conversationTests(app)
userCrudTests(app)