Write e2e tests for NestJS with testcontainers
So I was really annoyed last time I was trying to mock and have some tests for my NestJS app. So I decided to try testcontainers once more. Last time I was trying to mock BullMQ and it was giving me a hard time, and this time around I managed to get it working. Stick around and see how I did it. Support Me You can support me by giving my GitHub repo a star, so more developers start writing tests. I am a true believer of automated tests and TDD. Code So basically I really do not wanna spy one anything or mock for that matter. But rather I am only interested in knowing that my queue received a message and did its job, e.g. called an external API. Actually here I am not gonna test that but if you need to verify that the external API was called I think you can simply have a Wiremock Testcontainer and check it was called. I will not cover that case here, at least not now. But what I am interested to show you here is how the e2e test will look like: import { Test, TestingModule } from '@nestjs/testing'; import { INestApplication } from '@nestjs/common'; import { RedisContainer } from '@testcontainers/redis'; import * as request from 'supertest'; import { App } from 'supertest/types'; import { AppModule } from './../src/app.module'; describe('AppController (e2e)', () => { let app: INestApplication; beforeAll(async () => { const container = await new RedisContainer().start(); process.env.SERVICE_NAME = 'test'; process.env.REDIS_URI = container.getHostname(); process.env.REDIS_PORT = container.getPort().toString(); const moduleFixture: TestingModule = await Test.createTestingModule({ imports: [AppModule], }).compile(); app = moduleFixture.createNestApplication(); await app.init(); }); it('/ (GET)', async () => { const res = await request(app.getHttpServer()).get('/'); expect(res.status).toBe(200); expect(res.text).toBe('Hello World!'); }); }); NOTE Here I was not trying to use ConfigService, so I just hacked in my way into the process.env. But feel free to check my repo for a more mature way of dealing with env variables. GitHub Repo kasir-barati / nestjs-materials NestJS tips, tricks, Notes, Things which are not in doc and I used to figure them out and use them Important Keep this file synchronized with index.md. nestjs-materials NestJS tips, tricks, Notes, Things which are not in doc and I used to figure them out and use them Microservices gRPC. Protobuf. How to debug your code and flaky tests. A Crude Debug Mode For a Dockerized NestJS App. Designing and versioning RESTful APIs. Pagination. MockServer and mocking 3rd-party HTTP/S calls. Kafka intro. RabbitMQ intro. NestJS and GraphQL with nestjs-query View on GitHub Instagram: https://www.instagram.com/node.js.developers.kh/ Facebook: https://www.facebook.com/kasirbarati X: https://x.com/kasir_barati YouTube: https://www.youtube.com/@kasir-barati GitHub: https://github.com/kasir-barati/ Dev.to: https://dev.to/kasir-barati LinkedIn: https://linkedin.com/in/kasir-barati
So I was really annoyed last time I was trying to mock and have some tests for my NestJS app. So I decided to try testcontainers once more.
Last time I was trying to mock BullMQ and it was giving me a hard time, and this time around I managed to get it working.
Stick around and see how I did it.
Support Me
You can support me by giving my GitHub repo a star, so more developers start writing tests. I am a true believer of automated tests and TDD.
Code
So basically I really do not wanna spy one anything or mock for that matter. But rather I am only interested in knowing that my queue received a message and did its job, e.g. called an external API.
Actually here I am not gonna test that but if you need to verify that the external API was called I think you can simply have a Wiremock Testcontainer and check it was called.
I will not cover that case here, at least not now. But what I am interested to show you here is how the e2e test will look like:
import { Test, TestingModule } from '@nestjs/testing';
import { INestApplication } from '@nestjs/common';
import { RedisContainer } from '@testcontainers/redis';
import * as request from 'supertest';
import { App } from 'supertest/types';
import { AppModule } from './../src/app.module';
describe('AppController (e2e)', () => {
let app: INestApplication<App>;
beforeAll(async () => {
const container = await new RedisContainer().start();
process.env.SERVICE_NAME = 'test';
process.env.REDIS_URI = container.getHostname();
process.env.REDIS_PORT = container.getPort().toString();
const moduleFixture: TestingModule = await Test.createTestingModule({
imports: [AppModule],
}).compile();
app = moduleFixture.createNestApplication();
await app.init();
});
it('/ (GET)', async () => {
const res = await request(app.getHttpServer()).get('/');
expect(res.status).toBe(200);
expect(res.text).toBe('Hello World!');
});
});
NOTE
Here I was not trying to use
ConfigService
, so I just hacked in my way into theprocess.env
. But feel free to check my repo for a more mature way of dealing with env variables.
GitHub Repo
kasir-barati
/
nestjs-materials
NestJS tips, tricks, Notes, Things which are not in doc and I used to figure them out and use them
Important
Keep this file synchronized with index.md
.
nestjs-materials
NestJS tips, tricks, Notes, Things which are not in doc and I used to figure them out and use them
- Microservices
- How to debug your code and flaky tests.
- Designing and versioning RESTful APIs.
- MockServer and mocking 3rd-party HTTP/S calls.
- Kafka intro.
- RabbitMQ intro.
- NestJS and GraphQL with
nestjs-query
Instagram: https://www.instagram.com/node.js.developers.kh/
Facebook: https://www.facebook.com/kasirbarati
X: https://x.com/kasir_barati
YouTube: https://www.youtube.com/@kasir-barati
GitHub: https://github.com/kasir-barati/
Dev.to: https://dev.to/kasir-barati
LinkedIn: https://linkedin.com/in/kasir-barati