Skip to content

Commit

Permalink
Fix better error messages for circular dependencies (microsoft#42) (m…
Browse files Browse the repository at this point in the history
…icrosoft#90)

* Fix better error messages for circular dependencies (microsoft#42)

Ignore test cases folder.

* Rename imports folder to fixtures

* Code review fix typo in error message

* Move errorMatch helper to __tests__/utils scope.

* Fix tests after typo
  • Loading branch information
emilioastarita authored Feb 5, 2020
1 parent 75f769d commit 3f8b9e2
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 19 deletions.
43 changes: 24 additions & 19 deletions src/__tests__/errors.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {instance as globalContainer} from "../dependency-container";
import {inject, injectable} from "../decorators";

import {A01} from "./fixtures/01-test-case-A01-injects-B01";
import errorMatch from "./utils/error-match";
afterEach(() => {
globalContainer.reset();
});
Expand All @@ -26,16 +27,12 @@ test("Error message composition", () => {
expect(() => {
globalContainer.resolve(A);
}).toThrow(
new RegExp(
[
/Cannot inject the dependency "b" at position #1 of "A" constructor\. Reason:/,
/Cannot inject the dependency "c" at position #0 of "B" constructor\. Reason:/,
/Cannot inject the dependency "s" at position #0 of "C" constructor\. Reason:/,
/TypeInfo not known for "Object"/
]
.map(x => x.source)
.join("\\s+")
)
errorMatch([
/Cannot inject the dependency "b" at position #1 of "A" constructor\. Reason:/,
/Cannot inject the dependency "c" at position #0 of "B" constructor\. Reason:/,
/Cannot inject the dependency "s" at position #0 of "C" constructor\. Reason:/,
/TypeInfo not known for "Object"/
])
);
});

Expand All @@ -48,13 +45,21 @@ test("Param position", () => {
expect(() => {
globalContainer.resolve(A);
}).toThrow(
new RegExp(
[
/Cannot inject the dependency "j" at position #0 of "A" constructor\. Reason:/,
/Attempted to resolve unregistered dependency token: "missing"/
]
.map(x => x.source)
.join("\\s+")
)
errorMatch([
/Cannot inject the dependency "j" at position #0 of "A" constructor\. Reason:/,
/Attempted to resolve unregistered dependency token: "missing"/
])
);
});

test("Detect circular dependency", () => {
expect(() => {
globalContainer.resolve(A01);
}).toThrow(
errorMatch([
/Cannot inject the dependency "b" at position #0 of "A01" constructor\. Reason:/,
/Cannot inject the dependency "a" at position #0 of "B01" constructor\. Reason:/,
/Attempted to construct an undefined constructor. Could mean a circular dependency problem./
])
);
});
7 changes: 7 additions & 0 deletions src/__tests__/fixtures/01-test-case-A01-injects-B01.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import {B01} from "./01-test-case-B01-injects-A01";
import {injectable} from "../../decorators";

@injectable()
export class A01 {
constructor(public b: B01) {}
}
7 changes: 7 additions & 0 deletions src/__tests__/fixtures/01-test-case-B01-injects-A01.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import {A01} from "./01-test-case-A01-injects-B01";
import {injectable} from "../../decorators";

@injectable()
export class B01 {
constructor(public a: A01) {}
}
3 changes: 3 additions & 0 deletions src/__tests__/utils/error-match.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function errorMatch(lines: RegExp[]): RegExp {
return new RegExp(lines.map(x => x.source).join("\\s+"));
}
6 changes: 6 additions & 0 deletions src/dependency-container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,12 @@ class InternalDependencyContainer implements DependencyContainer {
}

private construct<T>(ctor: constructor<T>, context: ResolutionContext): T {
if (typeof ctor === "undefined") {
throw new Error(
"Attempted to construct an undefined constructor. Could mean a circular dependency problem."
);
}

if (ctor.length === 0) {
return new ctor();
}
Expand Down
1 change: 1 addition & 0 deletions test/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ module.exports = {
tsConfig: "src/__tests__/tsconfig.json"
}
},
testPathIgnorePatterns: ["/node_modules/", "/fixtures/", "/utils/"],
moduleFileExtensions: ["ts", "tsx", "js"],
setupFilesAfterEnv: ["<rootDir>/test/jest.setup.ts"],
testEnvironment: "node",
Expand Down

0 comments on commit 3f8b9e2

Please sign in to comment.