From 9230a2acc5323409a2aa17c532d17fa643ab5d79 Mon Sep 17 00:00:00 2001 From: Romain Lenzotti Date: Sun, 25 Aug 2024 10:18:24 +0200 Subject: [PATCH] fix(testcontainers-mongo): update readme package and add documentation --- docs/readme.md | 3 + docs/tutorials/mongoose.md | 179 +++++++++++------- .../snippets/mongoose/testing-api.jest.ts | 14 +- .../snippets/mongoose/testing-api.vitest.ts | 18 ++ .../snippets/mongoose/testing-model.jest.ts | 9 +- .../snippets/mongoose/testing-model.vitest.ts | 52 +++++ packages/orm/testcontainers-mongo/readme.md | 176 +++++++++-------- 7 files changed, 282 insertions(+), 169 deletions(-) create mode 100644 docs/tutorials/snippets/mongoose/testing-api.vitest.ts create mode 100644 docs/tutorials/snippets/mongoose/testing-model.vitest.ts diff --git a/docs/readme.md b/docs/readme.md index ccc63d4c167..57d35853123 100644 --- a/docs/readme.md +++ b/docs/readme.md @@ -211,6 +211,9 @@ frameworks: - title: Pulse href: /tutorials/pulse.html src: /pulse.png + - title: TestContainers + href: /tutorials/mongoose.html#testing + src: https://avatars.githubusercontent.com/u/13393021?s=200&v=4 --- ::: slot hero-brand diff --git a/docs/tutorials/mongoose.md b/docs/tutorials/mongoose.md index 961b9729ed7..aa6a4c95516 100644 --- a/docs/tutorials/mongoose.md +++ b/docs/tutorials/mongoose.md @@ -38,16 +38,40 @@ Currently, [`@tsed/mongoose`](https://www.npmjs.com/package/@tsed/mongoose) allo Before using the `@tsed/mongoose` package, we need to install the [mongoose](https://www.npmjs.com/package/mongoose) module. -```bash -npm install --save mongoose -npm install --save @tsed/mongoose -npm install --save-dev @tsed/testing-mongoose + + + +```sh [npm] +npm install --save mongoose @tsed/mongoose +npm install --save-dev @tsed/testcontainers-mongo ``` -::: warning -Since mongoose v5.11.0, the module expose his own file definition and can broke your build! -To solve it, install @tsed/mongoose v6.14.1 and remove the `@types/mongoose` dependencies. -::: + + + +```sh [yarn] +yarn add mongoose @tsed/mongoose +yarn add -D @tsed/testcontainers-mongo +``` + + + + +```sh [pnpm] +pnpm add mongoose @tsed/mongoose +pnpm add -D @tsed/testcontainers-mongo +``` + + + + +```sh [bun] +bun add mongoose @tsed/mongoose +bun add -D @tsed/testcontainers-mongo +``` + + + Then import `@tsed/mongoose` in your [Configuration](/docs/configuration.md): @@ -319,92 +343,84 @@ export class MyRepository { ## Testing -The package [`@tsed/testing-mongoose`](https://www.npmjs.com/package/@tsed/testing-mongoose) allows you to test your server with a memory database. +The [`@tsed/testcontainers-mongo`](https://www.npmjs.com/package/@tsed/testcontainers-mongo) package allows you to test your code using the [TestContainers](https://node.testcontainers.org/) library. -::: tip -This package uses the amazing [mongodb-memory-server](https://www.npmjs.com/package/mongodb-memory-server) to mock the mongo database. -::: +### Configuration -### Testing API - -This example shows you how you can test your Rest API with superagent and a mocked Mongo database: +To use the `@tsed/testcontainers-mongo` package, you need to install the package: - + -<<< @/tutorials/snippets/mongoose/testing-api.jest.ts +```sh [npm] +npm install --save-dev @tsed/testcontainers-mongo +``` - + -<<< @/tutorials/snippets/mongoose/testing-api.mocha.ts +```sh [yarn] +yarn add --dev @tsed/testcontainers-mongo +``` - + -::: tip -To increase mocha timeout from 2000ms to 10000ms use option `--timeout 10000`. -::: - -### Testing API with ReplicaSet +```sh [pnpm] +pnpm add --dev @tsed/testcontainers-mongo +``` -A [ReplicaSet](https://github.com/nodkz/mongodb-memory-server#replica-set-start) can be easily started with: + + -```typescript -import {PlatformTest} from "@tsed/common"; -import {PlatformExpress} from "@tsed/platform-express"; -import {TestMongooseContext} from "@tsed/testing-mongoose"; -import {expect} from "chai"; -import * as SuperTest from "supertest"; -import {Server} from "../Server"; - -describe("Rest", () => { - // bootstrap your Server to load all endpoints before run your test - let request: SuperTest.Agent; - - before( - TestMongooseContext.bootstrap(Server, { - platform: PlatformExpress, - mongod: { - replicaSet: true - } - }) - ); // Create a server with mocked database - before((done) => { - request = SuperTest(PlatformTest.callback()); - done(); - }); - - after(TestMongooseContext.reset); // reset database and injector - - describe("GET /rest/calendars", () => { - it("should do something", async () => { - const response = await request.get("/rest/calendars").expect(200); - - expect(response.body).to.be.an("array"); - }); - }); -}); +```sh [bun] +bun add --dev @tsed/testcontainers-mongo ``` -### Jest additional setup + + + +Then add or update your jest or vitest configuration file to add a global setup file: -Add a script to close connection after all unit test. In your jest configuration file add the following line: + + -```json -{ - "globalTeardown": "./scripts/jest/teardown.js" -} -``` +```ts [Jest] +// jest.config.js +module.exports = { + globalSetup: ["jest.setup.js"], + globalTeardown: ["jest.teardown.js"] +}; -And create the script with the following content: +// jest.setup.js +const {TestContainersMongo} = require("@tsed/testcontainers-mongo"); +module.exports = async () => { + await TestContainersMongo.startMongoServer(); +}; -```js +// jest.teardown.js +const {TestContainersMongo} = require("@tsed/testcontainers-mongo"); module.exports = async () => { - (await global.__MONGOD__) && global.__MONGOD__.stop(); + await TestContainersMongo.stopMongoServer(); }; ``` + + + +```ts [Vitest] +import {defineConfig} from "vitest/config"; + +export default defineConfig({ + test: { + globalSetup: [import.meta.resolve("@tsed/testcontainers-mongo/vitest/setup")] + } +}); +``` + + + + ### Testing Model This example shows you how can test the model: @@ -415,13 +431,30 @@ This example shows you how can test the model: <<< @/tutorials/snippets/mongoose/testing-model.jest.ts - + -<<< @/tutorials/snippets/mongoose/testing-model.mocha.ts +<<< @/tutorials/snippets/mongoose/testing-model.vitest.ts +### Testing API + +This example shows you how you can test your Rest API with superagent and a mocked Mongo database: + + + + +<<< @/tutorials/snippets/mongoose/testing-api.jest.ts + + + + +<<< @/tutorials/snippets/mongoose/testing-api.jest.ts + + + + ## Author diff --git a/docs/tutorials/snippets/mongoose/testing-api.jest.ts b/docs/tutorials/snippets/mongoose/testing-api.jest.ts index b465f31e42c..237becab2ed 100644 --- a/docs/tutorials/snippets/mongoose/testing-api.jest.ts +++ b/docs/tutorials/snippets/mongoose/testing-api.jest.ts @@ -1,21 +1,15 @@ import {PlatformTest} from "@tsed/common"; -import {TestMongooseContext} from "@tsed/testing-mongoose"; +import {TestContainersMongo} from "@tsed/testcontainers-mongo"; import * as SuperTest from "supertest"; import {Server} from "../Server"; describe("Rest", () => { - // bootstrap your Server to load all endpoints before run your test - let request: SuperTest.Agent; - - before(TestMongooseContext.bootstrap(Server)); // Create a server with mocked database - before(() => { - request = SuperTest(PlatformTest.callback()); - }); - - after(TestMongooseContext.reset); // reset database and injector + beforeAll(TestContainersMongo.bootstrap(Server)); // Create a server with mocked database + afterAll(() => TestContainersMongo.reset()); // reset database and injector describe("GET /rest/calendars", () => { it("should do something", async () => { + const request = SuperTest(PlatformTest.callback()); const response = await request.get("/rest/calendars").expect(200); expect(typeof response.body).toEqual("array"); diff --git a/docs/tutorials/snippets/mongoose/testing-api.vitest.ts b/docs/tutorials/snippets/mongoose/testing-api.vitest.ts new file mode 100644 index 00000000000..237becab2ed --- /dev/null +++ b/docs/tutorials/snippets/mongoose/testing-api.vitest.ts @@ -0,0 +1,18 @@ +import {PlatformTest} from "@tsed/common"; +import {TestContainersMongo} from "@tsed/testcontainers-mongo"; +import * as SuperTest from "supertest"; +import {Server} from "../Server"; + +describe("Rest", () => { + beforeAll(TestContainersMongo.bootstrap(Server)); // Create a server with mocked database + afterAll(() => TestContainersMongo.reset()); // reset database and injector + + describe("GET /rest/calendars", () => { + it("should do something", async () => { + const request = SuperTest(PlatformTest.callback()); + const response = await request.get("/rest/calendars").expect(200); + + expect(typeof response.body).toEqual("array"); + }); + }); +}); diff --git a/docs/tutorials/snippets/mongoose/testing-model.jest.ts b/docs/tutorials/snippets/mongoose/testing-model.jest.ts index 43f2d6b7fb4..307c90bda86 100644 --- a/docs/tutorials/snippets/mongoose/testing-model.jest.ts +++ b/docs/tutorials/snippets/mongoose/testing-model.jest.ts @@ -1,6 +1,7 @@ -import {PlatformTest, Property, Required} from "@tsed/common"; +import {PlatformTest} from "@tsed/common"; +import {Property, Required} from "@tsed/schema"; import {Model, MongooseModel, ObjectID, PostHook, PreHook, Unique} from "@tsed/mongoose"; -import {TestMongooseContext} from "@tsed/testing-mongoose"; +import {TestContainersMongo} from "@tsed/testcontainers-mongo"; @Model({schemaOptions: {timestamps: true}}) @PreHook("save", (user: UserModel, next: any) => { @@ -30,8 +31,8 @@ export class UserModel { } describe("UserModel", () => { - beforeEach(TestMongooseContext.create); - afterEach(TestMongooseContext.reset); + beforeEach(() => TestContainersMongo.create()); + afterEach(() => TestContainersMongo.reset("users")); // clean users collection after each test it("should run pre and post hook", async () => { const userModel = PlatformTest.get>(UserModel); diff --git a/docs/tutorials/snippets/mongoose/testing-model.vitest.ts b/docs/tutorials/snippets/mongoose/testing-model.vitest.ts new file mode 100644 index 00000000000..307c90bda86 --- /dev/null +++ b/docs/tutorials/snippets/mongoose/testing-model.vitest.ts @@ -0,0 +1,52 @@ +import {PlatformTest} from "@tsed/common"; +import {Property, Required} from "@tsed/schema"; +import {Model, MongooseModel, ObjectID, PostHook, PreHook, Unique} from "@tsed/mongoose"; +import {TestContainersMongo} from "@tsed/testcontainers-mongo"; + +@Model({schemaOptions: {timestamps: true}}) +@PreHook("save", (user: UserModel, next: any) => { + user.pre = "hello pre"; + + next(); +}) +@PostHook("save", (user: UserModel, next: any) => { + user.post = "hello post"; + + next(); +}) +export class UserModel { + @ObjectID("id") + _id: string; + + @Property() + @Required() + @Unique() + email: string; + + @Property() + pre: string; + + @Property() + post: string; +} + +describe("UserModel", () => { + beforeEach(() => TestContainersMongo.create()); + afterEach(() => TestContainersMongo.reset("users")); // clean users collection after each test + + it("should run pre and post hook", async () => { + const userModel = PlatformTest.get>(UserModel); + + // GIVEN + const user = new userModel({ + email: "test@test.fr" + }); + + // WHEN + await user.save(); + + // THEN + expect(user.pre).toEqual("hello pre"); + expect(user.post).toEqual("hello post"); + }); +}); diff --git a/packages/orm/testcontainers-mongo/readme.md b/packages/orm/testcontainers-mongo/readme.md index 5c069092317..a241316ee03 100644 --- a/packages/orm/testcontainers-mongo/readme.md +++ b/packages/orm/testcontainers-mongo/readme.md @@ -3,7 +3,7 @@

-

Mongoose testing

+

TestContainers Mongo

[![Build & Release](https://github.com/tsedio/tsed/workflows/Build%20&%20Release/badge.svg)](https://github.com/tsedio/tsed/actions?query=workflow%3A%22Build+%26+Release%22) [![PR Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://github.com/tsedio/tsed/blob/master/CONTRIBUTING.md) @@ -29,111 +29,123 @@ A package of Ts.ED framework. See website: https://tsed.io/ -This package is an helper to create unit test base on `@tsed/mongoose` package. +This package allows you to test your code using the [TestContainers](https://node.testcontainers.org/) library. # Installation -```bash -npm install --save @tsed/testing-mongoose +To use the `@tsed/testcontainers-mongo` package, you need to install the package: + +```sh [npm] +npm install --save-dev @tsed/testcontainers-mongo ``` -## Example usage +```sh [yarn] +yarn add --dev @tsed/testcontainers-mongo +``` -### Testing server +```sh [pnpm] +pnpm add --dev @tsed/testcontainers-mongo +``` -Here an example to your server with a mocked database: +```sh [bun] +bun add --dev @tsed/testcontainers-mongo +``` -```typescript -import {PlatformTest} from "@tsed/common"; -import {PlatformExpress} from "@tsed/platform-express"; -import {TestMongooseContext} from "@tsed/testing-mongoose"; -import {expect} from "chai"; -import * as SuperTest from "supertest"; -import {Server} from "../Server.js"; - -describe("Rest", () => { - // bootstrap your Server to load all endpoints before run your test - let request: SuperTest.Agent; - - before(TestMongooseContext.bootstrap(Server, {platform: PlatformExpress})); // Create a server with mocked database - before((done) => { - request = SuperTest(PlatformTest.callback()); - done(); - }); +### Configuration - after(TestMongooseContext.reset); // reset database and injector +Add or update your jest or vitest configuration file to add a global setup file: - describe("GET /rest/calendars", () => { - it("should do something", async () => { - const response = await request.get("/rest/calendars").expect(200); +#### Jest - expect(response.body).to.be.an("array"); - }); - }); -}); -``` - -::: tip -To increase mocha timeout from 2000ms to 10000ms use option `--timeout 10000`. -::: - -### Testing server with Replica set +```ts +// jest.config.js +module.exports = { + globalSetup: ["jest.setup.js"], + globalTeardown: ["jest.teardown.js"] +}; -A [ReplicaSet](https://github.com/nodkz/mongodb-memory-server#replica-set-start) can be easily started with: +// jest.setup.js +const {TestContainersMongo} = require("@tsed/testcontainers-mongo"); +module.exports = async () => { + await TestContainersMongo.startMongoServer(); +}; -```typescript -import {PlatformTest} from "@tsed/common"; -import {PlatformExpress} from "@tsed/platform-express"; -import {TestMongooseContext} from "@tsed/testing-mongoose"; -import {expect} from "chai"; -import * as SuperTest from "supertest"; -import {Server} from "../Server.js"; - -describe("Rest", () => { - // bootstrap your Server to load all endpoints before run your test - let request: SuperTest.Agent; - - before( - TestMongooseContext.bootstrap(Server, { - platform: PlatformExpress, - mongod: { - replicaSet: true - } - }) - ); // Create a server with mocked database - before((done) => { - request = SuperTest(PlatformTest.callback()); - done(); - }); +// jest.teardown.js +const {TestContainersMongo} = require("@tsed/testcontainers-mongo"); +module.exports = async () => { + await TestContainersMongo.stopMongoServer(); +}; +``` - after(TestMongooseContext.reset); // reset database and injector +### Vitest - describe("GET /rest/calendars", () => { - it("should do something", async () => { - const response = await request.get("/rest/calendars").expect(200); +```ts +import {defineConfig} from "vitest/config"; - expect(response.body).to.be.an("array"); - }); - }); +export default defineConfig({ + test: { + globalSetup: [import.meta.resolve("@tsed/testcontainers-mongo/vitest/setup")] + } }); ``` -## Jest additional setup +::: -Add a script to close connection after all unit test. In your jest configuration file add the following line: +### Usage -```json -{ - "globalTeardown": "./scripts/jest/teardown.js" +```ts +import {PlatformTest} from "@tsed/common"; +import {Property, Required} from "@tsed/schema"; +import {Model, MongooseModel, ObjectID, PostHook, PreHook, Unique} from "@tsed/mongoose"; +import {TestContainersMongo} from "@tsed/testcontainers-mongo"; + +@Model({schemaOptions: {timestamps: true}}) +@PreHook("save", (user: UserModel, next: any) => { + user.pre = "hello pre"; + + next(); +}) +@PostHook("save", (user: UserModel, next: any) => { + user.post = "hello post"; + + next(); +}) +export class UserModel { + @ObjectID("id") + _id: string; + + @Property() + @Required() + @Unique() + email: string; + + @Property() + pre: string; + + @Property() + post: string; } -``` -And create the script with the following content: +describe("UserModel", () => { + beforeEach(() => TestContainersMongo.create()); + afterEach(() => TestContainersMongo.reset("users")); // clean users collection after each test -```js -module.exports = async () => { - await global.__MONGOD__.stop(); -}; + it("should run pre and post hook", async () => { + const userModel = PlatformTest.get>(UserModel); + + // GIVEN + const user = new userModel({ + email: "test@test.fr" + }); + + // WHEN + await user.save(); + + // THEN + expect(user.pre).toEqual("hello pre"); + expect(user.post).toEqual("hello post"); + }); +}); ``` ## Contributors