Skip to content

Commit

Permalink
fix(di): fix asynchronous factory injection when PlatformTest.invoke …
Browse files Browse the repository at this point in the history
…is used
  • Loading branch information
Romakita committed Mar 28, 2024
1 parent 0f14089 commit 069e01a
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 2 deletions.
1 change: 1 addition & 0 deletions packages/di/package.json
Expand Up @@ -30,6 +30,7 @@
"@tsed/schema": "workspace:*",
"@tsed/typescript": "workspace:*",
"barrelsby": "^2.8.1",
"cross-env": "7.0.3",
"eslint": "^8.57.0",
"jest": "^29.7.0"
},
Expand Down
56 changes: 56 additions & 0 deletions packages/di/src/node/integration/async-factory-invoke.spec.ts
@@ -0,0 +1,56 @@
import {Inject, Injectable, registerProvider, DITest} from "../../index";

const PrimaryPostgresDb = Symbol.for("PrimaryPostgresDb");
type PrimaryPostgresDb = {id: string};

registerProvider({
provide: PrimaryPostgresDb,
useAsyncFactory: () => {
return Promise.resolve({
id: "id"
});
}
});

@Injectable()
export class MyService {
@Inject(PrimaryPostgresDb)
protected dataSource: PrimaryPostgresDb;

me() {
return this.dataSource.id;
}
}

describe("AsyncFactory", () => {
beforeEach(() => DITest.create());
afterEach(() => DITest.reset());

it("should inject async factory and return resolve promise value (first test)", () => {
const service = DITest.get<MyService>(MyService);

const result = service.me();
expect(result).toEqual("id");
});

it("should inject async factory and return resolve promise value (second test)", () => {
const service = DITest.get<MyService>(MyService);

const result = service.me();
expect(result).toEqual("id");
});

it("should inject async factory and return resolve promise value (first test - invoke)", async () => {
const service = await DITest.invoke<MyService>(MyService, []);

const result = service.me();
expect(result).toEqual("id");
});

it("should inject async factory and return resolve promise value (second test - invoke)", async () => {
const service = await DITest.invoke<MyService>(MyService, []);

const result = service.me();
expect(result).toEqual("id");
});
});
25 changes: 25 additions & 0 deletions packages/di/src/node/integration/invoke-oninit.spec.ts
@@ -0,0 +1,25 @@
import {Inject, Injectable, registerProvider, DITest} from "../../index";

@Injectable()
export class MyService {
id = "id";
$onInit() {
return new Promise((resolve) =>
setTimeout(() => {
this.id = "id2";
resolve({});
}, 1)
);
}
}

describe("OnInit Invoke", () => {
beforeEach(() => DITest.create());
afterEach(() => DITest.reset());

it("should inject async factory and return resolve promise value", async () => {
const service = await DITest.invoke<MyService>(MyService, []);

expect(service.id).toEqual("id2");
});
});
9 changes: 7 additions & 2 deletions packages/di/src/node/services/DITest.ts
@@ -1,4 +1,4 @@
import {Env, getValue, setValue} from "@tsed/core";
import {Env, getValue, isClass, isPromise, setValue} from "@tsed/core";
import {$log} from "@tsed/logger";
import {createContainer, InjectorService, LocalsContainer, OnInit, TokenProvider, TokenProviderOpts} from "../../common/index";
import {DIContext} from "../domain/DIContext";
Expand Down Expand Up @@ -84,7 +84,7 @@ export class DITest {
* @param target
* @param providers
*/
static invoke<T = any>(target: TokenProvider, providers: TokenProviderOpts[] = []): T | Promise<T> {
static async invoke<T = any>(target: TokenProvider, providers: TokenProviderOpts[] = []): Promise<T> {
const locals = new LocalsContainer();
providers.forEach((p) => {
locals.set(p.token, p.use);
Expand All @@ -97,11 +97,16 @@ export class DITest {
if (instance && instance.$onInit) {
// await instance.$onInit();
const result = instance.$onInit();

if (result instanceof Promise) {
return result.then(() => instance as any);
}
}

if (isClass(instance)) {
await Promise.all(Object.values(instance).filter(isPromise));
}

return instance as any;
}

Expand Down
1 change: 1 addition & 0 deletions yarn.lock
Expand Up @@ -6680,6 +6680,7 @@ __metadata:
"@tsed/schema": "workspace:*"
"@tsed/typescript": "workspace:*"
barrelsby: "npm:^2.8.1"
cross-env: "npm:7.0.3"
eslint: "npm:^8.57.0"
jest: "npm:^29.7.0"
tslib: "npm:2.6.2"
Expand Down

0 comments on commit 069e01a

Please sign in to comment.