From 2a390ddf2d7d968ff0a1f22fde4562561f8992bc Mon Sep 17 00:00:00 2001 From: Romain Lenzotti Date: Sun, 8 Sep 2024 20:09:26 +0200 Subject: [PATCH] feat(testcontainers-mongo): use mongodb to clean collection instead of @tsed/mongoose The module can be used with mongoose or mikro-orm. --- packages/orm/mikro-orm/package.json | 1 + .../orm/mikro-orm/test/integration.spec.ts | 23 +++++---- packages/orm/mikro-orm/tsconfig.json | 2 +- packages/orm/mikro-orm/vitest.config.mts | 4 +- packages/orm/mongoose/package.json | 1 + .../mongoose/test/array.integration.spec.ts | 5 +- packages/orm/mongoose/tsconfig.json | 3 ++ packages/orm/mongoose/vitest.setup.mts | 10 ---- .../orm/testcontainers-mongo/package.json | 4 +- packages/orm/testcontainers-mongo/readme.md | 43 +++++++++++++++- .../src/services/TestContainersMongo.ts | 38 ++++++++------ .../orm/testcontainers-mongo/tsconfig.json | 3 -- yarn.lock | 49 ++++++++++--------- 13 files changed, 117 insertions(+), 69 deletions(-) delete mode 100644 packages/orm/mongoose/vitest.setup.mts diff --git a/packages/orm/mikro-orm/package.json b/packages/orm/mikro-orm/package.json index 1c838874d88..f8ac6fd95d2 100644 --- a/packages/orm/mikro-orm/package.json +++ b/packages/orm/mikro-orm/package.json @@ -35,6 +35,7 @@ "@tsed/json-mapper": "workspace:*", "@tsed/logger": ">=6.7.5", "@tsed/schema": "workspace:*", + "@tsed/testcontainers-mongo": "workspace:*", "@tsed/typescript": "workspace:*", "cross-env": "7.0.3", "eslint": "^8.57.0", diff --git a/packages/orm/mikro-orm/test/integration.spec.ts b/packages/orm/mikro-orm/test/integration.spec.ts index c0b3eb96f0b..0945cbf5d80 100644 --- a/packages/orm/mikro-orm/test/integration.spec.ts +++ b/packages/orm/mikro-orm/test/integration.spec.ts @@ -10,33 +10,36 @@ import {Hooks} from "./helpers/services/Hooks.js"; import {UnmanagedEventSubscriber1} from "./helpers/services/UnmanagedEventSubscriber1.js"; import {UnmanagedEventSubscriber2} from "./helpers/services/UnmanagedEventSubscriber2.js"; import {UserService} from "./helpers/services/UserService.js"; +import {TestContainersMongo} from "@tsed/testcontainers-mongo"; -describe.skip("MikroOrm integration", () => { +describe("MikroOrm integration", () => { let spiedLogger!: Logger; let spiedTransactionalInterceptor!: TransactionalInterceptor; let spiedHooks!: Hooks; beforeEach(async () => { -// await TestMongooseContext.install({replicaSet: true}); - // const {url: clientUrl} = await TestMongooseContext.getMongooseOptions(); + const mongoSettings = TestContainersMongo.getMongoConnectionOptions(); const bstrp = PlatformTest.bootstrap(Server, { disableComponentScan: true, imports: [MikroOrmModule], mikroOrm: [ defineConfig({ - clientUrl, + clientUrl: mongoSettings.url, entities: [User], - subscribers: [UnmanagedEventSubscriber1, new UnmanagedEventSubscriber2()] + subscribers: [UnmanagedEventSubscriber1, new UnmanagedEventSubscriber2()], + driverOptions: mongoSettings.connectionOptions }), defineConfig({ - clientUrl, + clientUrl: mongoSettings.url, contextName: "db1", - entities: [User] + entities: [User], + driverOptions: mongoSettings.connectionOptions }), defineConfig({ - clientUrl, + clientUrl: mongoSettings.url, contextName: "db2", - entities: [User] + entities: [User], + driverOptions: mongoSettings.connectionOptions }) ] }); @@ -51,7 +54,7 @@ describe.skip("MikroOrm integration", () => { afterEach(async () => { reset(spiedLogger, spiedTransactionalInterceptor, spiedHooks); - // await TestMongooseContext.reset(); + await TestContainersMongo.reset(); }); it("should return repository", () => { diff --git a/packages/orm/mikro-orm/tsconfig.json b/packages/orm/mikro-orm/tsconfig.json index f531ae64d7d..3ec1c68049e 100644 --- a/packages/orm/mikro-orm/tsconfig.json +++ b/packages/orm/mikro-orm/tsconfig.json @@ -22,7 +22,7 @@ "path": "../../specs/schema/tsconfig.json" }, { - "path": "../testing-mongoose/tsconfig.json" + "path": "../testcontainers-mongo/tsconfig.json" }, { "path": "./tsconfig.cjs.json" diff --git a/packages/orm/mikro-orm/vitest.config.mts b/packages/orm/mikro-orm/vitest.config.mts index 59bdf026b05..acee1f791bc 100644 --- a/packages/orm/mikro-orm/vitest.config.mts +++ b/packages/orm/mikro-orm/vitest.config.mts @@ -7,6 +7,8 @@ export default defineConfig( ...presets, test: { ...presets.test, + // @ts-ignore + globalSetup: [import.meta.resolve("@tsed/testcontainers-mongo/vitest/setup")], coverage: { ...presets.test.coverage, thresholds: { @@ -18,4 +20,4 @@ export default defineConfig( } } } -); \ No newline at end of file +); diff --git a/packages/orm/mongoose/package.json b/packages/orm/mongoose/package.json index 2477e6d90a9..583a1bc4986 100644 --- a/packages/orm/mongoose/package.json +++ b/packages/orm/mongoose/package.json @@ -41,6 +41,7 @@ "@tsed/json-mapper": "workspace:*", "@tsed/logger": ">=6.7.5", "@tsed/schema": "workspace:*", + "@tsed/testcontainers-mongo": "workspace:*", "@tsed/typescript": "workspace:*", "eslint": "^8.57.0", "mongoose": "6.12.7", diff --git a/packages/orm/mongoose/test/array.integration.spec.ts b/packages/orm/mongoose/test/array.integration.spec.ts index 7f918d49ea3..578c7c3bb7e 100644 --- a/packages/orm/mongoose/test/array.integration.spec.ts +++ b/packages/orm/mongoose/test/array.integration.spec.ts @@ -1,6 +1,7 @@ import {serialize} from "@tsed/json-mapper"; import {MyWorkspace, UserModel, UserWorkspace, Workspace, WorkspaceModel} from "./helpers/models/UserWorkspace.js"; import {TestContainersMongo} from "@tsed/testcontainers-mongo"; +import {DITest} from "@tsed/di"; describe("Mongoose", () => { describe("Array models", () => { @@ -8,8 +9,8 @@ describe("Mongoose", () => { afterEach(() => TestContainersMongo.reset()); it("should run pre and post hook", async () => { - const userModel = PlatformTest.get(UserWorkspace); - const workspaceModel = PlatformTest.get(Workspace); + const userModel = DITest.get(UserWorkspace); + const workspaceModel = DITest.get(Workspace); // GIVEN const user = new userModel(); diff --git a/packages/orm/mongoose/tsconfig.json b/packages/orm/mongoose/tsconfig.json index 89178569535..7c0154121de 100644 --- a/packages/orm/mongoose/tsconfig.json +++ b/packages/orm/mongoose/tsconfig.json @@ -21,6 +21,9 @@ { "path": "../../specs/schema/tsconfig.json" }, + { + "path": "../testcontainers-mongo/tsconfig.json" + }, { "path": "./tsconfig.cjs.json" }, diff --git a/packages/orm/mongoose/vitest.setup.mts b/packages/orm/mongoose/vitest.setup.mts deleted file mode 100644 index 5a150c7a111..00000000000 --- a/packages/orm/mongoose/vitest.setup.mts +++ /dev/null @@ -1,10 +0,0 @@ -import { startMongoServer, stopMongoServer } from "./test/helpers/TestContainerMongo.js"; - - -export async function setup() { - await startMongoServer(); -} - -export async function teardown() { - await stopMongoServer(); -} diff --git a/packages/orm/testcontainers-mongo/package.json b/packages/orm/testcontainers-mongo/package.json index 331c1b1c47e..3ccc82dd3c4 100644 --- a/packages/orm/testcontainers-mongo/package.json +++ b/packages/orm/testcontainers-mongo/package.json @@ -34,9 +34,9 @@ "@tsed/common": "workspace:*", "@tsed/core": "workspace:*", "@tsed/di": "workspace:*", - "@tsed/mongoose": "workspace:*", "@tsed/typescript": "workspace:*", "eslint": "^8.57.0", + "mongodb": "6.8.0", "testcontainers": ">=10.11.0", "typescript": "4.9.5" }, @@ -45,7 +45,7 @@ "@tsed/common": "8.0.0-alpha.1", "@tsed/core": "8.0.0-alpha.1", "@tsed/di": "8.0.0-alpha.1", - "@tsed/mongoose": "8.0.0-alpha.1", + "mongodb": ">=6", "testcontainers": ">=10.11.0" } } diff --git a/packages/orm/testcontainers-mongo/readme.md b/packages/orm/testcontainers-mongo/readme.md index a241316ee03..23372560c47 100644 --- a/packages/orm/testcontainers-mongo/readme.md +++ b/packages/orm/testcontainers-mongo/readme.md @@ -91,7 +91,13 @@ export default defineConfig({ ::: -### Usage +## Usage + +### @tsed/mongoose + +#### Unit test + +Use the `TestContainersMongo.create` method to start the mongo server before your test: ```ts import {PlatformTest} from "@tsed/common"; @@ -148,6 +154,41 @@ describe("UserModel", () => { }); ``` +#### Integration test + +Just use the `TestContainersMongo.bootstrap` method to start the mongo server before your test: + +```ts +beforeEach(() => TestContainersMongo.bootstrap(Server, {})); +``` + +### Mikro ORM + +TestContainersMongo provides a method to get the connection options for MikroORM: + +```ts +import {EntityManager, MikroORM} from "@mikro-orm/core"; +import {defineConfig} from "@mikro-orm/mongodb"; +import {PlatformTest} from "@tsed/common"; +import {TestContainersMongo} from "@tsed/testcontainers-mongo"; + +beforeEach(async () => { + const mongoSettings = TestContainersMongo.getMongoConnectionOptions(); + const bstrp = PlatformTest.bootstrap(Server, { + disableComponentScan: true, + imports: [MikroOrmModule], + mikroOrm: [ + defineConfig({ + clientUrl: mongoSettings.url, + driverOptions: mongoSettings.connectionOptions, + entities: [User], + subscribers: [UnmanagedEventSubscriber1, new UnmanagedEventSubscriber2()] + }) + ] + }); +}); +``` + ## Contributors Please read [contributing guidelines here](https://tsed.io/contributing.html) diff --git a/packages/orm/testcontainers-mongo/src/services/TestContainersMongo.ts b/packages/orm/testcontainers-mongo/src/services/TestContainersMongo.ts index a151f64a541..e7ea503225d 100644 --- a/packages/orm/testcontainers-mongo/src/services/TestContainersMongo.ts +++ b/packages/orm/testcontainers-mongo/src/services/TestContainersMongo.ts @@ -1,5 +1,5 @@ import {PlatformTest} from "@tsed/common"; -import {MongooseService} from "@tsed/mongoose"; +import {MongoClient} from "mongodb"; import {getMongoConnectionOptions, getMongoConnectionsOptions, startMongoServer, stopMongoServer} from "./ContainerUtils.js"; export class TestContainersMongo { @@ -8,19 +8,25 @@ export class TestContainersMongo { static getMongoConnectionsOptions = getMongoConnectionsOptions; static getMongoConnectionOptions = getMongoConnectionOptions; + private static configuration: ReturnType; + static create(options: Partial = {}) { + TestContainersMongo.configuration = getMongoConnectionsOptions(); + return PlatformTest.create({ ...options, - mongoose: getMongoConnectionsOptions() + mongoose: TestContainersMongo.configuration }); } static bootstrap(mod: unknown, opts: Partial = {}) { - return () => - PlatformTest.bootstrap(mod, { - mongoose: getMongoConnectionsOptions(), + return () => { + TestContainersMongo.configuration = getMongoConnectionsOptions(); + return PlatformTest.bootstrap(mod, { + mongoose: TestContainersMongo.configuration, ...opts })(); + }; } static async reset(collectionName?: string) { @@ -31,16 +37,18 @@ export class TestContainersMongo { return PlatformTest.reset(); } - static async cleanCollection(collectionName: string) { - const service = PlatformTest.injector.get(MongooseService)!; - - const {collections} = service.get("default")!; - - if (!collections[collectionName]) { - console.error(`Collection ${collectionName} not found. Here available collection names: ${Object.keys(collections)}`); - return; + static async cleanCollection(collectionName: string, mongoSettings = TestContainersMongo.configuration) { + try { + const client = new MongoClient(mongoSettings[0].url, { + directConnection: true + }); + + await client.connect(); + const db = client.db(); + await db.collection(collectionName).deleteMany({}); + await client.close(); + } catch (er) { + console.error(`Collection ${collectionName} not found. ${er.message} ${er.stack}`); } - - await collections[collectionName].deleteMany({}); } } diff --git a/packages/orm/testcontainers-mongo/tsconfig.json b/packages/orm/testcontainers-mongo/tsconfig.json index 7ce985f91de..250467edb65 100644 --- a/packages/orm/testcontainers-mongo/tsconfig.json +++ b/packages/orm/testcontainers-mongo/tsconfig.json @@ -15,9 +15,6 @@ { "path": "../../di/tsconfig.json" }, - { - "path": "../mongoose/tsconfig.json" - }, { "path": "./tsconfig.cjs.json" }, diff --git a/yarn.lock b/yarn.lock index 058ac0e3f42..7f5d9805602 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6897,7 +6897,7 @@ __metadata: "@tsed/json-mapper": "workspace:*" "@tsed/logger": "npm:>=6.7.5" "@tsed/schema": "workspace:*" - "@tsed/testing-mongoose": "workspace:*" + "@tsed/testcontainers-mongo": "workspace:*" "@tsed/typescript": "workspace:*" cross-env: "npm:7.0.3" eslint: "npm:^8.57.0" @@ -6925,6 +6925,7 @@ __metadata: "@tsed/json-mapper": "workspace:*" "@tsed/logger": "npm:>=6.7.5" "@tsed/schema": "workspace:*" + "@tsed/testcontainers-mongo": "workspace:*" "@tsed/typescript": "workspace:*" change-case: "npm:4.1.2" eslint: "npm:^8.57.0" @@ -8114,7 +8115,7 @@ __metadata: languageName: unknown linkType: soft -"@tsed/testcontainers-mongo@workspace:packages/orm/testcontainers-mongo": +"@tsed/testcontainers-mongo@workspace:*, @tsed/testcontainers-mongo@workspace:packages/orm/testcontainers-mongo": version: 0.0.0-use.local resolution: "@tsed/testcontainers-mongo@workspace:packages/orm/testcontainers-mongo" dependencies: @@ -8123,9 +8124,9 @@ __metadata: "@tsed/common": "workspace:*" "@tsed/core": "workspace:*" "@tsed/di": "workspace:*" - "@tsed/mongoose": "workspace:*" "@tsed/typescript": "workspace:*" eslint: "npm:^8.57.0" + mongodb: "npm:6.8.0" semver: "npm:^7.6.0" testcontainers: "npm:>=10.11.0" tslib: "npm:2.6.1" @@ -8135,12 +8136,12 @@ __metadata: "@tsed/common": 8.0.0-alpha.1 "@tsed/core": 8.0.0-alpha.1 "@tsed/di": 8.0.0-alpha.1 - "@tsed/mongoose": 8.0.0-alpha.1 + mongodb: ">=6" testcontainers: ">=10.11.0" languageName: unknown linkType: soft -"@tsed/testing-mongoose@workspace:*, @tsed/testing-mongoose@workspace:packages/orm/testing-mongoose": +"@tsed/testing-mongoose@workspace:packages/orm/testing-mongoose": version: 0.0.0-use.local resolution: "@tsed/testing-mongoose@workspace:packages/orm/testing-mongoose" dependencies: @@ -22375,25 +22376,7 @@ __metadata: languageName: node linkType: hard -"mongodb@npm:^4.16.0": - version: 4.17.1 - resolution: "mongodb@npm:4.17.1" - dependencies: - "@aws-sdk/credential-providers": "npm:^3.186.0" - "@mongodb-js/saslprep": "npm:^1.1.0" - bson: "npm:^4.7.2" - mongodb-connection-string-url: "npm:^2.6.0" - socks: "npm:^2.7.1" - dependenciesMeta: - "@aws-sdk/credential-providers": - optional: true - "@mongodb-js/saslprep": - optional: true - checksum: 10/2ce62912ab36885e927c109a699568174cc61025bc03e2d5c22e6070aaec967b2364d4b9d42c9131531c2547416b57d14952c50235d43fa66e76a6fbe4c96c37 - languageName: node - linkType: hard - -"mongodb@npm:^6.5.0": +"mongodb@npm:6.8.0, mongodb@npm:^6.5.0": version: 6.8.0 resolution: "mongodb@npm:6.8.0" dependencies: @@ -22427,6 +22410,24 @@ __metadata: languageName: node linkType: hard +"mongodb@npm:^4.16.0": + version: 4.17.1 + resolution: "mongodb@npm:4.17.1" + dependencies: + "@aws-sdk/credential-providers": "npm:^3.186.0" + "@mongodb-js/saslprep": "npm:^1.1.0" + bson: "npm:^4.7.2" + mongodb-connection-string-url: "npm:^2.6.0" + socks: "npm:^2.7.1" + dependenciesMeta: + "@aws-sdk/credential-providers": + optional: true + "@mongodb-js/saslprep": + optional: true + checksum: 10/2ce62912ab36885e927c109a699568174cc61025bc03e2d5c22e6070aaec967b2364d4b9d42c9131531c2547416b57d14952c50235d43fa66e76a6fbe4c96c37 + languageName: node + linkType: hard + "mongoose@npm:6.5.1": version: 6.5.1 resolution: "mongoose@npm:6.5.1"