Test express API with jest

Viewed 56

I'm currently learning how to create API with typescript and i'm trying to test API using jest framework. I know that using it with basic express application like

app = express()

supertest(app)

works fine. But i have a custom App class which throws errors when trying to do the same to it.(API without tests works fine). Is there a way to test it with jest?

api.test.ts

import { app } from '../../src/index';
import supertest from 'supertest';

describe('/users', () => {
it('Should return: 401 Unauthorized', async () => {
    await supertest(app).get('/api/users').expect(401, {
        status: 401,
         message: 'Unauthorized',
      });
   });
});

app.ts

class App {
public express: Application;
public port: number;

constructor(controllers: Controller[], port: number) {
    this.express = express();
    this.port = port;
    this.initializeDatabaseConnection();
    this.initializeMiddleware();
    this.initializeControllers(controllers);
    this.initializeErrorHandling();
}

private initializeDatabaseConnection(): void {
    const { MONGO_URI } = process.env;
    mongoose.connect(`${MONGO_URI}`);
}

private initializeMiddleware(): void {
    this.express.use(helmet());
    this.express.use(cors());
    this.express.use(morgan('dev'));
    this.express.use(express.urlencoded({ extended: false }));
    this.express.use(express.json());
    this.express.use(compression());
}

private initializeControllers(controllers: Controller[]): void {
    controllers.forEach((controller: Controller) => {
        this.express.use('/api', controller.router);
    });
}

private initializeErrorHandling(): void {
    this.express.use(ErrorHandler);
}

public listen(): void {
    this.express.listen(this.port, () => {
        console.log(`App is running on port ${this.port}`);
    });
}
}

export default App;

index.ts

import FlightController from './resources/flight/flight.controller';
import 'dotenv/config';
import App from './app';
import validateEnv from './utils/validateEnv';
import UserController from './resources/user/user.controller';

validateEnv();

export const app = new App(
    [new FlightController(), new UserController()],
    Number(process.env.PORT)
);

app.listen();

ERROR

  ●  Cannot log after tests are done. Did you forget to wait for something async in your test?
    Attempted to log "App is running on port 3000".

      42 |
      43 |     private initializeErrorHandling(): void {
    > 44 |         this.express.use(ErrorHandler);
         |                     ^
      45 |     }
      46 |
      47 |     public listen(): void {

      at console.log (node_modules/@jest/console/build/CustomConsole.js:172:10)
      at Server.<anonymous> (src/app.ts:44:21)



FAIL  __tests__/e2e/flight.api.test.ts
  /users                                                                                                                        
    × should return 200 and user info (2 ms)                                                                                    
                                                                                                                                
  ● /users › should return 200 and user info                                                                                    
                                                                                                                                
    TypeError: app.address is not a function

      4 | describe('/users', () => {
      5 |     it('should return 200 and user info', async () => {
    > 6 |         await request(app).get('/api/users').expect(401, {
        |                            ^
      7 |             status: 401,
      8 |             message: 'Unauthorized',
      9 |         });
1 Answers

Seeing Express Written in typescript gives me chill

Either way to your fix, it seem your try get run supertest(app) as an await code without declaring the function as an [Async Function]

describe('/users', () => {
it('Should return: 401 Unauthorized', async () => {
    await supertest(app).get('/api/users').expect(401, {
        status: 401,
         message: 'Unauthorized',
      });
   });
});

So Your fix should be

// Add the async keyword
describe('/users', async () => {
it('Should return: 401 Unauthorized', async () => {
    await supertest(app).get('/api/users').expect(401, {
        status: 401,
         message: 'Unauthorized',
      });
   });
});
Related