Skip to content

Commit 3f8b9e2

Browse files
Fix better error messages for circular dependencies (#42) (#90)
* Fix better error messages for circular dependencies (#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
1 parent 75f769d commit 3f8b9e2

File tree

6 files changed

+48
-19
lines changed

6 files changed

+48
-19
lines changed

src/__tests__/errors.test.ts

+24-19
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import {instance as globalContainer} from "../dependency-container";
22
import {inject, injectable} from "../decorators";
3-
3+
import {A01} from "./fixtures/01-test-case-A01-injects-B01";
4+
import errorMatch from "./utils/error-match";
45
afterEach(() => {
56
globalContainer.reset();
67
});
@@ -26,16 +27,12 @@ test("Error message composition", () => {
2627
expect(() => {
2728
globalContainer.resolve(A);
2829
}).toThrow(
29-
new RegExp(
30-
[
31-
/Cannot inject the dependency "b" at position #1 of "A" constructor\. Reason:/,
32-
/Cannot inject the dependency "c" at position #0 of "B" constructor\. Reason:/,
33-
/Cannot inject the dependency "s" at position #0 of "C" constructor\. Reason:/,
34-
/TypeInfo not known for "Object"/
35-
]
36-
.map(x => x.source)
37-
.join("\\s+")
38-
)
30+
errorMatch([
31+
/Cannot inject the dependency "b" at position #1 of "A" constructor\. Reason:/,
32+
/Cannot inject the dependency "c" at position #0 of "B" constructor\. Reason:/,
33+
/Cannot inject the dependency "s" at position #0 of "C" constructor\. Reason:/,
34+
/TypeInfo not known for "Object"/
35+
])
3936
);
4037
});
4138

@@ -48,13 +45,21 @@ test("Param position", () => {
4845
expect(() => {
4946
globalContainer.resolve(A);
5047
}).toThrow(
51-
new RegExp(
52-
[
53-
/Cannot inject the dependency "j" at position #0 of "A" constructor\. Reason:/,
54-
/Attempted to resolve unregistered dependency token: "missing"/
55-
]
56-
.map(x => x.source)
57-
.join("\\s+")
58-
)
48+
errorMatch([
49+
/Cannot inject the dependency "j" at position #0 of "A" constructor\. Reason:/,
50+
/Attempted to resolve unregistered dependency token: "missing"/
51+
])
52+
);
53+
});
54+
55+
test("Detect circular dependency", () => {
56+
expect(() => {
57+
globalContainer.resolve(A01);
58+
}).toThrow(
59+
errorMatch([
60+
/Cannot inject the dependency "b" at position #0 of "A01" constructor\. Reason:/,
61+
/Cannot inject the dependency "a" at position #0 of "B01" constructor\. Reason:/,
62+
/Attempted to construct an undefined constructor. Could mean a circular dependency problem./
63+
])
5964
);
6065
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import {B01} from "./01-test-case-B01-injects-A01";
2+
import {injectable} from "../../decorators";
3+
4+
@injectable()
5+
export class A01 {
6+
constructor(public b: B01) {}
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import {A01} from "./01-test-case-A01-injects-B01";
2+
import {injectable} from "../../decorators";
3+
4+
@injectable()
5+
export class B01 {
6+
constructor(public a: A01) {}
7+
}

src/__tests__/utils/error-match.ts

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export default function errorMatch(lines: RegExp[]): RegExp {
2+
return new RegExp(lines.map(x => x.source).join("\\s+"));
3+
}

src/dependency-container.ts

+6
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,12 @@ class InternalDependencyContainer implements DependencyContainer {
337337
}
338338

339339
private construct<T>(ctor: constructor<T>, context: ResolutionContext): T {
340+
if (typeof ctor === "undefined") {
341+
throw new Error(
342+
"Attempted to construct an undefined constructor. Could mean a circular dependency problem."
343+
);
344+
}
345+
340346
if (ctor.length === 0) {
341347
return new ctor();
342348
}

test/jest.config.js

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ module.exports = {
1414
tsConfig: "src/__tests__/tsconfig.json"
1515
}
1616
},
17+
testPathIgnorePatterns: ["/node_modules/", "/fixtures/", "/utils/"],
1718
moduleFileExtensions: ["ts", "tsx", "js"],
1819
setupFilesAfterEnv: ["<rootDir>/test/jest.setup.ts"],
1920
testEnvironment: "node",

0 commit comments

Comments
 (0)