Skip to main content
Version: 3.0.0

Testing

Unit and integration testing are both crucial in application development, each serving a unique purpose:

  • Unit tests: Focus on testing individual pieces of code, like a single function or method, in isolation. Dependencies are mocked to ensure controlled, reliable testing. Unit tests help catch bugs early and ensure that each part of the code works correctly, simplifying debugging later.

  • Integration tests: Test the interaction between different components and external services. Unlike unit tests, they evaluate the application as a whole to ensure all parts work together as expected.

tip

Combining unit tests and integration tests can be beneficial because it allows developers to test both individual units of code and the application as a whole. This helps ensure that each piece of code is working correctly on its own and in conjunction with other parts of the application.

Our goal

Our goal is to provide a simple and easy way to test your ExpressoTS APIs. We are working on a test library that wraps a modern testing framework to provide a simple and intuitive API for writing unit and integration tests. The test library will include:

  • A test runner
  • Adding the test library of your choice
  • A test suite
  • A test case
  • A test assertion library
  • A test coverage tool
  • CLI command to scaffold tests
Stay tuned for updates on our test library!

Testing usage example

We will demonstrate how to test a simple ExpressoTS API using Jest and Supertest. You can use the test library of your choice.

Below we are testing the PingUseCase endpoint return. We are using the Jest as the test runner and ts-jest as the TypeScript preprocessor.

ping.use-case.spec.ts
describe("PingUseCase", () => {
let pingUseCase: PingUseCase;

beforeEach(() => {
pingUseCase = new PingUseCase();
});

it("should return a valid PingResponseDTO", () => {
const start: Date = new Date();
const response = pingUseCase.execute(start);
const end: Date = new Date(response.end);
const ttl = parseFloat(response.ttl.split(" ")[0]);

expect(response).toHaveProperty("start");
expect(response).toHaveProperty("end");
expect(response).toHaveProperty("ttl");
expect(response).toHaveProperty("message");
expect(response.message).toBe("Pong!");
expect(start <= end).toBe(true);
expect(ttl >= 0).toBe(true);
});
});

E2E testing with supertest

We have available a method called getHttpServer() in the AppExpress class that returns a proxy to the Express server. This method is useful for testing the application using Supertest.

Alonside with this method, we have the close() method that closes the server and releases the resources.

GET /v1 test
import { AppFactory, StatusCode } from "@expressots/core";
import { IWebServerPublic } from "@expressots/shared";

import express from "express";
import request from "supertest";

import { App } from "../src/app";

describe("App Test", () => {
let server: express.Application;
let appInstance: IWebServerPublic;

beforeAll(async () => {
appInstance = await AppFactory.create(App);
await appInstance.listen(3000);

server = await appInstance.getHttpServer();
});

afterAll(async () => {
await appInstance.close();
});

it("returns a valid app response", async () => {
return request(server).get("/v1").expect(StatusCode.OK).expect("Hello from ExpressoTS!");
});
});

Support us ❤️

ExpressoTS is an MIT-licensed open source project. It's an independent project with ongoing development made possible thanks to your support. If you'd like to help, please read our support guide.