@codefast/di-testing 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/README.md +140 -63
  3. package/dist/discovery/dependency-scanner.d.ts +1 -2
  4. package/dist/discovery/dependency-scanner.js +1 -2
  5. package/dist/discovery/mock-binder.d.ts +1 -2
  6. package/dist/discovery/mock-binder.js +1 -2
  7. package/dist/errors/errors.d.ts +1 -2
  8. package/dist/errors/errors.js +1 -2
  9. package/dist/index.d.ts +1 -2
  10. package/dist/index.js +1 -2
  11. package/dist/mocking/auto-mock.d.ts +1 -2
  12. package/dist/mocking/auto-mock.js +1 -2
  13. package/dist/mocking/mock-factory.d.ts +1 -2
  14. package/dist/mocking/mock-factory.js +1 -2
  15. package/dist/mocking/spy.d.ts +1 -2
  16. package/dist/mocking/spy.js +1 -2
  17. package/dist/test-bed/bed-builder.d.ts +1 -2
  18. package/dist/test-bed/bed-builder.js +1 -2
  19. package/dist/test-bed/sociable-builder.d.ts +1 -2
  20. package/dist/test-bed/sociable-builder.js +1 -2
  21. package/dist/test-bed/solitary-builder.d.ts +1 -2
  22. package/dist/test-bed/solitary-builder.js +1 -2
  23. package/dist/test-bed/test-bed.d.ts +1 -2
  24. package/dist/test-bed/test-bed.js +1 -2
  25. package/dist/test-bed/unit-test-bed.d.ts +1 -2
  26. package/dist/test-bed/unit-test-bed.js +1 -2
  27. package/dist/types.d.ts +1 -2
  28. package/dist/types.js +1 -2
  29. package/package.json +7 -29
  30. package/dist/discovery/dependency-scanner.d.ts.map +0 -1
  31. package/dist/discovery/dependency-scanner.js.map +0 -1
  32. package/dist/discovery/mock-binder.d.ts.map +0 -1
  33. package/dist/discovery/mock-binder.js.map +0 -1
  34. package/dist/errors/errors.d.ts.map +0 -1
  35. package/dist/errors/errors.js.map +0 -1
  36. package/dist/index.d.ts.map +0 -1
  37. package/dist/index.js.map +0 -1
  38. package/dist/mocking/auto-mock.d.ts.map +0 -1
  39. package/dist/mocking/auto-mock.js.map +0 -1
  40. package/dist/mocking/mock-factory.d.ts.map +0 -1
  41. package/dist/mocking/mock-factory.js.map +0 -1
  42. package/dist/mocking/spy.d.ts.map +0 -1
  43. package/dist/mocking/spy.js.map +0 -1
  44. package/dist/test-bed/bed-builder.d.ts.map +0 -1
  45. package/dist/test-bed/bed-builder.js.map +0 -1
  46. package/dist/test-bed/sociable-builder.d.ts.map +0 -1
  47. package/dist/test-bed/sociable-builder.js.map +0 -1
  48. package/dist/test-bed/solitary-builder.d.ts.map +0 -1
  49. package/dist/test-bed/solitary-builder.js.map +0 -1
  50. package/dist/test-bed/test-bed.d.ts.map +0 -1
  51. package/dist/test-bed/test-bed.js.map +0 -1
  52. package/dist/test-bed/unit-test-bed.d.ts.map +0 -1
  53. package/dist/test-bed/unit-test-bed.js.map +0 -1
  54. package/dist/types.d.ts.map +0 -1
  55. package/dist/types.js.map +0 -1
  56. package/src/discovery/dependency-scanner.ts +0 -80
  57. package/src/discovery/mock-binder.ts +0 -334
  58. package/src/errors/errors.ts +0 -119
  59. package/src/index.ts +0 -26
  60. package/src/mocking/auto-mock.ts +0 -243
  61. package/src/mocking/mock-factory.ts +0 -35
  62. package/src/mocking/spy.ts +0 -92
  63. package/src/test-bed/bed-builder.ts +0 -172
  64. package/src/test-bed/sociable-builder.ts +0 -148
  65. package/src/test-bed/solitary-builder.ts +0 -70
  66. package/src/test-bed/test-bed.ts +0 -64
  67. package/src/test-bed/unit-test-bed.ts +0 -161
  68. package/src/types.ts +0 -15
@@ -1,148 +0,0 @@
1
- /** The fluent builder that compiles a unit together with chosen real collaborators. */
2
-
3
- import type { Constructor, DependencySlot, InjectOptions } from "@codefast/di";
4
- import { Container, token } from "@codefast/di";
5
-
6
- import { scanSociableDependencies } from "#/discovery/dependency-scanner";
7
- import { bindMocks } from "#/discovery/mock-binder";
8
- import { ExposureError } from "#/errors/errors";
9
- import type { MockFunction } from "#/mocking/mock-factory";
10
- import type { Spy } from "#/mocking/spy";
11
- import type { MockOverrideBuilder, PreparedBed } from "#/test-bed/bed-builder";
12
- import { BedBuilder } from "#/test-bed/bed-builder";
13
- import type { SociableUnitTestBed } from "#/test-bed/unit-test-bed";
14
- import { createSociableUnitTestBed, createUnitTestBed } from "#/test-bed/unit-test-bed";
15
- import type { InjectionIdentifier } from "#/types";
16
-
17
- /**
18
- * A sociable build in progress: expose real collaborators, override the rest, then compile.
19
- *
20
- * @remarks Exposure follows class identity: a class-keyed dependency of the unit — or of another
21
- * exposed class — stays real when exposed. A `Token`-keyed dependency is always mocked, treating
22
- * tokens as the declared boundary between the logic under test and the outside world.
23
- *
24
- * @typeParam Class - The class under test.
25
- * @typeParam Backend - The spy type the bed's mock factory produces.
26
- *
27
- * @since 0.1.0
28
- */
29
- export interface SociableTestBedBuilder<Class, Backend extends MockFunction = Spy> {
30
- /** Keeps a class-keyed collaborator real; its own dependencies follow the same exposure rules. */
31
- expose(target: Constructor): SociableTestBedBuilder<Class, Backend>;
32
- /** Replaces the auto-mock for one dependency with a hand-written stub or a concrete value. */
33
- mock<Dependency>(
34
- identifier: InjectionIdentifier<Dependency>,
35
- options?: InjectOptions,
36
- ): MockOverrideBuilder<Dependency, SociableTestBedBuilder<Class, Backend>, Backend>;
37
- /** Instantiates the unit and its exposed subtree, mocking everything else. */
38
- compile(): SociableUnitTestBed<Class, Backend>;
39
- /** Async variant for a subtree whose `@postConstruct` is async; otherwise identical to {@link compile}. */
40
- compileAsync(): Promise<SociableUnitTestBed<Class, Backend>>;
41
- }
42
-
43
- /** What the sociable prepare step adds to the shared shape: the reachable exposed classes. */
44
- type PreparedSociableBed = PreparedBed & { readonly realClasses: ReadonlySet<Constructor> };
45
-
46
- /**
47
- * The default {@link SociableTestBedBuilder}, backed by a fresh container per compile.
48
- *
49
- * @typeParam Class - The class under test.
50
- * @typeParam Backend - The spy type the bed's mock factory produces.
51
- *
52
- * @since 0.1.0
53
- */
54
- export class SociableBuilder<Class, Backend extends MockFunction = Spy>
55
- extends BedBuilder<Class, Backend>
56
- implements SociableTestBedBuilder<Class, Backend>
57
- {
58
- readonly #exposed = new Set<Constructor>();
59
-
60
- expose(target: Constructor): this {
61
- this.#exposed.add(target);
62
- return this;
63
- }
64
-
65
- compile(): SociableUnitTestBed<Class, Backend> {
66
- return this.compileWith(
67
- () => this.#prepare(),
68
- (unit, prepared) =>
69
- createSociableUnitTestBed(
70
- createUnitTestBed(unit, prepared.mocks, prepared.container),
71
- prepared.container,
72
- prepared.realClasses,
73
- ),
74
- );
75
- }
76
-
77
- async compileAsync(): Promise<SociableUnitTestBed<Class, Backend>> {
78
- return this.compileWithAsync(
79
- () => this.#prepare(),
80
- (unit, prepared) =>
81
- createSociableUnitTestBed(
82
- createUnitTestBed(unit, prepared.mocks, prepared.container),
83
- prepared.container,
84
- prepared.realClasses,
85
- ),
86
- );
87
- }
88
-
89
- /** Scans across the exposed set, binds mocks for the boundary, and binds every real class. */
90
- #prepare(): PreparedSociableBed {
91
- if (this.#exposed.has(this.target)) {
92
- throw new ExposureError(this.target.name, "the unit under test is already real — expose only its collaborators.");
93
- }
94
-
95
- const container = Container.create({ metadataReader: this.reader });
96
- const { mockSlots, realClasses, realSlots } = scanSociableDependencies(this.target, this.#exposed, this.reader);
97
-
98
- // An exposed class the unit never reaches is a stale exposure — likely a typo or a refactor.
99
- for (const exposedClass of this.#exposed) {
100
- if (!realClasses.has(exposedClass)) {
101
- throw new ExposureError(
102
- exposedClass.name,
103
- "the unit never reaches this class through exposed collaborators. Expose the intermediate classes on the path to it, or remove the exposure.",
104
- );
105
- }
106
- }
107
-
108
- const mocks = bindMocks(container, mockSlots, this.overrides, this.mockFactory, this.#exposed);
109
-
110
- const constrainedSlots = new Map<Constructor, Array<DependencySlot>>();
111
- for (const slot of realSlots) {
112
- const list = constrainedSlots.get(slot.token as Constructor) ?? [];
113
- list.push(slot);
114
- constrainedSlots.set(slot.token as Constructor, list);
115
- }
116
-
117
- // Real collaborators are singletons, so the unit and bed.exposed() see one instance each,
118
- // and their @preDestroy hooks run on dispose.
119
- const merged = new Map(mocks);
120
- for (const realClass of realClasses) {
121
- const slots = constrainedSlots.get(realClass);
122
- if (slots === undefined) {
123
- container.bind(realClass).toSelf().singleton();
124
- } else {
125
- // A name/tag-constrained slot needs its own binding, and di rejects a self-alias — so the
126
- // one real binding lives on a private token, and every slot of the class resolves it
127
- // through a factory (an alias would forward the slot's criteria to the private token).
128
- const realToken = token<unknown>(`di-testing:real:${realClass.name}`);
129
- container.bind(realToken).to(realClass).singleton();
130
- container.bind(realClass).toDynamic((context) => context.resolve(realToken));
131
- for (const slot of slots) {
132
- const builder = container.bind(realClass).toDynamic((context) => context.resolve(realToken));
133
- if (slot.name !== undefined) {
134
- builder.whenNamed(slot.name);
135
- }
136
- for (const tag of slot.tags ?? []) {
137
- builder.whenTagged(tag);
138
- }
139
- }
140
- }
141
- // Sealed entries so mocks.get points at bed.exposed() instead of handing back a fake Mocked.
142
- merged.set(realClass, [{ criteria: undefined, value: undefined, kind: "exposed" }]);
143
- }
144
- container.bind(this.target).toSelf().singleton();
145
-
146
- return { container, mocks: merged, realClasses };
147
- }
148
- }
@@ -1,70 +0,0 @@
1
- /** The fluent builder that compiles a solitary unit under test. */
2
-
3
- import type { InjectOptions } from "@codefast/di";
4
- import { Container } from "@codefast/di";
5
-
6
- import { scanDependencies } from "#/discovery/dependency-scanner";
7
- import { bindMocks } from "#/discovery/mock-binder";
8
- import type { MockFunction } from "#/mocking/mock-factory";
9
- import type { Spy } from "#/mocking/spy";
10
- import type { MockOverrideBuilder, PreparedBed } from "#/test-bed/bed-builder";
11
- import { BedBuilder } from "#/test-bed/bed-builder";
12
- import type { UnitTestBed } from "#/test-bed/unit-test-bed";
13
- import { createUnitTestBed } from "#/test-bed/unit-test-bed";
14
- import type { InjectionIdentifier } from "#/types";
15
-
16
- /**
17
- * A solitary build in progress: register overrides, then compile.
18
- *
19
- * @typeParam Class - The class under test.
20
- * @typeParam Backend - The spy type the bed's mock factory produces.
21
- *
22
- * @since 0.1.0
23
- */
24
- export interface SolitaryTestBedBuilder<Class, Backend extends MockFunction = Spy> {
25
- /** Replaces the auto-mock for one dependency with a hand-written stub or a concrete value. */
26
- mock<Dependency>(
27
- identifier: InjectionIdentifier<Dependency>,
28
- options?: InjectOptions,
29
- ): MockOverrideBuilder<Dependency, SolitaryTestBedBuilder<Class, Backend>, Backend>;
30
- /** Instantiates the unit with every dependency mocked, running accessor injection and `@postConstruct`. */
31
- compile(): UnitTestBed<Class, Backend>;
32
- /** Async variant for a unit whose `@postConstruct` is async; otherwise identical to {@link compile}. */
33
- compileAsync(): Promise<UnitTestBed<Class, Backend>>;
34
- }
35
-
36
- /**
37
- * The default {@link SolitaryTestBedBuilder}, backed by a fresh container per compile.
38
- *
39
- * @typeParam Class - The class under test.
40
- * @typeParam Backend - The spy type the bed's mock factory produces.
41
- *
42
- * @since 0.1.0
43
- */
44
- export class SolitaryBuilder<Class, Backend extends MockFunction = Spy>
45
- extends BedBuilder<Class, Backend>
46
- implements SolitaryTestBedBuilder<Class, Backend>
47
- {
48
- compile(): UnitTestBed<Class, Backend> {
49
- return this.compileWith(
50
- () => this.#prepare(),
51
- (unit, prepared) => createUnitTestBed(unit, prepared.mocks, prepared.container),
52
- );
53
- }
54
-
55
- async compileAsync(): Promise<UnitTestBed<Class, Backend>> {
56
- return this.compileWithAsync(
57
- () => this.#prepare(),
58
- (unit, prepared) => createUnitTestBed(unit, prepared.mocks, prepared.container),
59
- );
60
- }
61
-
62
- /** Builds the container, binds every dependency's mock, and registers the unit as a singleton. */
63
- #prepare(): PreparedBed {
64
- const container = Container.create({ metadataReader: this.reader });
65
- const dependencies = scanDependencies(this.target, this.reader);
66
- const mocks = bindMocks(container, dependencies, this.overrides, this.mockFactory);
67
- container.bind(this.target).toSelf().singleton();
68
- return { container, mocks };
69
- }
70
- }
@@ -1,64 +0,0 @@
1
- /** The entry point for building isolated units under test. */
2
-
3
- import type { Constructor } from "@codefast/di";
4
-
5
- import type { MockFunction } from "#/mocking/mock-factory";
6
- import type { Spy } from "#/mocking/spy";
7
- import type { TestBedOptions } from "#/test-bed/bed-builder";
8
- import { SociableBuilder } from "#/test-bed/sociable-builder";
9
- import type { SociableTestBedBuilder } from "#/test-bed/sociable-builder";
10
- import { SolitaryBuilder } from "#/test-bed/solitary-builder";
11
- import type { SolitaryTestBedBuilder } from "#/test-bed/solitary-builder";
12
-
13
- /**
14
- * The factory surface for building isolated units under test.
15
- *
16
- * @since 0.1.0
17
- */
18
- export interface TestBedStatic {
19
- /**
20
- * Begins a solitary test bed for `target`, auto-mocking every dependency it declares.
21
- *
22
- * @remarks The mock factory's return type becomes `Backend` and types every mock the bed hands
23
- * out — pass `{ mockFactory: () => vi.fn() }` and `mocks.get(X).method` carries Vitest's own
24
- * mock surface.
25
- */
26
- solitary<Class, Backend extends MockFunction = Spy>(
27
- target: Constructor<Class>,
28
- options?: TestBedOptions<Backend>,
29
- ): SolitaryTestBedBuilder<Class, Backend>;
30
-
31
- /**
32
- * Begins a sociable test bed for `target`: chosen class collaborators stay real, tokens stay mocked.
33
- *
34
- * @remarks Returns only `expose` — a sociable bed without at least one exposed collaborator is a
35
- * solitary bed, so the type steers the first call.
36
- */
37
- sociable<Class, Backend extends MockFunction = Spy>(
38
- target: Constructor<Class>,
39
- options?: TestBedOptions<Backend>,
40
- ): Pick<SociableTestBedBuilder<Class, Backend>, "expose">;
41
- }
42
-
43
- /**
44
- * Entry point for auto-mocking a class in isolation from its collaborators.
45
- *
46
- * @remarks `solitary` and `sociable` record the target and options only; nothing is instantiated
47
- * until `compile()`.
48
- *
49
- * @since 0.1.0
50
- */
51
- export const TestBed: TestBedStatic = {
52
- solitary<Class, Backend extends MockFunction = Spy>(
53
- target: Constructor<Class>,
54
- options?: TestBedOptions<Backend>,
55
- ): SolitaryTestBedBuilder<Class, Backend> {
56
- return new SolitaryBuilder<Class, Backend>(target, options);
57
- },
58
- sociable<Class, Backend extends MockFunction = Spy>(
59
- target: Constructor<Class>,
60
- options?: TestBedOptions<Backend>,
61
- ): Pick<SociableTestBedBuilder<Class, Backend>, "expose"> {
62
- return new SociableBuilder<Class, Backend>(target, options);
63
- },
64
- };
@@ -1,161 +0,0 @@
1
- /// <reference lib="esnext.disposable" />
2
-
3
- /** The compiled result of a test bed: the real unit plus handles to its mocks. */
4
-
5
- import type { Constructor, Container, DependencyKey, InjectOptions, TokenValue } from "@codefast/di";
6
- import { tokenName } from "@codefast/di";
7
-
8
- import type { BoundMock } from "#/discovery/mock-binder";
9
- import { criteriaEquals, normalizeCriteria } from "#/discovery/mock-binder";
10
- import { ExposureError, SealedDependencyError, UndeclaredDependencyError } from "#/errors/errors";
11
- import type { Mocked } from "#/mocking/auto-mock";
12
- import { MOCK_RESET } from "#/mocking/auto-mock";
13
- import type { MockFunction } from "#/mocking/mock-factory";
14
- import type { Spy } from "#/mocking/spy";
15
-
16
- /**
17
- * A lookup from a dependency's token or class to the mock the unit was built with.
18
- *
19
- * @typeParam Backend - The spy type the bed's mock factory produces.
20
- *
21
- * @since 0.1.0
22
- */
23
- export interface UnitReference<Backend extends MockFunction = Spy> {
24
- /**
25
- * Retrieves the mock bound for one of the unit's dependencies, typed to that dependency's value.
26
- *
27
- * @remarks Pass `options` (a name or tags) to address one slot of a token injected several ways.
28
- * Only auto-mocks and `.stub` seeds come back — a value supplied with `.using()`, `.absent()`, or
29
- * `.usingAll()` is sealed, and an exposed class is real, so neither has a mock surface for the
30
- * `Mocked` type to describe.
31
- *
32
- * @throws UndeclaredDependencyError When the identifier or slot is not one of the unit's dependencies.
33
- * @throws SealedDependencyError When the dependency was supplied as a sealed value or exposed.
34
- */
35
- get<Identifier extends DependencyKey>(
36
- identifier: Identifier,
37
- options?: InjectOptions,
38
- ): Mocked<TokenValue<Identifier>, Backend>;
39
- }
40
-
41
- /**
42
- * A compiled unit: the real class under test, plus a handle to every mock it received.
43
- *
44
- * @remarks Implements `AsyncDisposable`, so `await using bed = TestBed.solitary(X).compile()` runs
45
- * the unit's `@preDestroy` hooks and disposes the backing container at the end of the block.
46
- *
47
- * @typeParam Class - The class under test.
48
- * @typeParam Backend - The spy type the bed's mock factory produces.
49
- *
50
- * @since 0.1.0
51
- */
52
- export interface UnitTestBed<Class, Backend extends MockFunction = Spy> extends AsyncDisposable {
53
- readonly unit: Class;
54
- readonly mocks: UnitReference<Backend>;
55
- /** Clears the call history and configured behaviour of every auto-mock and stub the bed created. */
56
- resetMocks(this: void): void;
57
- /** Runs the unit's `@preDestroy` hooks and disposes the backing container. */
58
- dispose(this: void): Promise<void>;
59
- }
60
-
61
- /**
62
- * A sociable bed: the solitary surface plus access to the real collaborators it exposed.
63
- *
64
- * @typeParam Class - The class under test.
65
- * @typeParam Backend - The spy type the bed's mock factory produces.
66
- *
67
- * @since 0.1.0
68
- */
69
- export interface SociableUnitTestBed<Class, Backend extends MockFunction = Spy> extends UnitTestBed<Class, Backend> {
70
- /**
71
- * Returns the real instance of an exposed collaborator — the one the unit was actually built with.
72
- *
73
- * @throws ExposureError When the class was not exposed.
74
- */
75
- exposed<Real>(target: Constructor<Real>): Real;
76
- }
77
-
78
- /**
79
- * Wraps a compiled bed with access to its exposed real collaborators.
80
- *
81
- * @since 0.1.0
82
- */
83
- export function createSociableUnitTestBed<Class, Backend extends MockFunction = Spy>(
84
- bed: UnitTestBed<Class, Backend>,
85
- container: Container,
86
- exposedClasses: ReadonlySet<Constructor>,
87
- ): SociableUnitTestBed<Class, Backend> {
88
- // Copied member by member, so a future bed with accessor or prototype members cannot be dropped
89
- // silently by a spread.
90
- return {
91
- unit: bed.unit,
92
- mocks: bed.mocks,
93
- resetMocks: bed.resetMocks,
94
- dispose: bed.dispose,
95
- [Symbol.asyncDispose]: bed[Symbol.asyncDispose],
96
- exposed<Real>(target: Constructor<Real>): Real {
97
- if (!exposedClasses.has(target)) {
98
- throw new ExposureError(target.name, "the class was not exposed. Add .expose(Class) before compile().");
99
- }
100
- // Exposed classes are singletons the unit's construction already instantiated.
101
- return container.resolve(target);
102
- },
103
- };
104
- }
105
-
106
- /**
107
- * Assembles a {@link UnitTestBed} around an instantiated unit and its bound mock entries.
108
- *
109
- * @since 0.1.0
110
- */
111
- export function createUnitTestBed<Class, Backend extends MockFunction = Spy>(
112
- unit: Class,
113
- entries: ReadonlyMap<DependencyKey, ReadonlyArray<BoundMock>>,
114
- container: Container,
115
- ): UnitTestBed<Class, Backend> {
116
- const mocks: UnitReference<Backend> = {
117
- get<Identifier extends DependencyKey>(
118
- identifier: Identifier,
119
- options?: InjectOptions,
120
- ): Mocked<TokenValue<Identifier>, Backend> {
121
- const bound = entries.get(identifier);
122
- if (bound === undefined) {
123
- throw new UndeclaredDependencyError(tokenName(identifier));
124
- }
125
- const criteria = normalizeCriteria(options);
126
- const entry =
127
- criteria === undefined
128
- ? (bound.find((candidate) => candidate.criteria === undefined) ?? (bound.length === 1 ? bound[0] : undefined))
129
- : bound.find((candidate) => candidate.criteria !== undefined && criteriaEquals(candidate.criteria, criteria));
130
- if (entry === undefined) {
131
- throw new UndeclaredDependencyError(tokenName(identifier), "no such slot");
132
- }
133
- if (entry.kind !== "auto" && entry.kind !== "stub") {
134
- throw new SealedDependencyError(tokenName(identifier), entry.kind);
135
- }
136
- return entry.value as Mocked<TokenValue<Identifier>, Backend>;
137
- },
138
- };
139
-
140
- const resetMocks = (): void => {
141
- for (const bound of entries.values()) {
142
- for (const entry of bound) {
143
- if (entry.kind === "auto" || entry.kind === "stub") {
144
- (entry.value as { [MOCK_RESET]?: () => void })[MOCK_RESET]?.();
145
- }
146
- }
147
- }
148
- };
149
-
150
- const dispose = async (): Promise<void> => {
151
- await container.dispose();
152
- };
153
-
154
- return {
155
- unit,
156
- mocks,
157
- resetMocks,
158
- dispose,
159
- [Symbol.asyncDispose]: dispose,
160
- };
161
- }
package/src/types.ts DELETED
@@ -1,15 +0,0 @@
1
- /** Shared vocabulary the test bed keys its dependencies by. */
2
-
3
- import type { Constructor, Token } from "@codefast/di";
4
-
5
- /**
6
- * A token or class constructor used to identify one of the unit's dependencies.
7
- *
8
- * @remarks The value-typed counterpart of di's own `DependencyKey`: it carries `Value` so
9
- * `mocks.get()` can map an identifier back to the mock type it produced.
10
- *
11
- * @typeParam Value - The value type the identified dependency resolves to.
12
- *
13
- * @since 0.1.0
14
- */
15
- export type InjectionIdentifier<Value> = Token<Value> | Constructor<Value>;