Skip to content

Commit 0c6385d

Browse files
Merge pull request nestjs#3653 from jacob87o2/fix-unknown-dependency-exception
fix(core): fix unknown dependency exception (symbols)
2 parents 7505849 + 00d5263 commit 0c6385d

5 files changed

Lines changed: 44 additions & 10 deletions

File tree

integration/injector/e2e/property-injection.spec.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { expect } from 'chai';
33
import { DependencyService } from '../src/properties/dependency.service';
44
import { PropertiesModule } from '../src/properties/properties.module';
55
import { PropertiesService } from '../src/properties/properties.service';
6+
import { UnknownDependenciesException } from '@nestjs/core/errors/exceptions/unknown-dependencies.exception';
67

78
describe('Injector', () => {
89
it('should resolve property-based dependencies', async () => {
@@ -14,5 +15,30 @@ describe('Injector', () => {
1415

1516
expect(app.get(PropertiesService).service).to.be.eql(dependency);
1617
expect(app.get(PropertiesService).token).to.be.true;
18+
expect(app.get(PropertiesService).symbolToken).to.be.true;
19+
});
20+
21+
it('should throw UnknownDependenciesException when dependency is not met', async () => {
22+
let exception;
23+
24+
try {
25+
const builder = Test.createTestingModule({
26+
providers: [
27+
DependencyService,
28+
PropertiesService,
29+
{
30+
provide: 'token',
31+
useValue: true,
32+
},
33+
// symbol token is missing here
34+
],
35+
});
36+
const app = await builder.compile();
37+
app.get(DependencyService);
38+
} catch (e) {
39+
exception = e;
40+
}
41+
42+
expect(exception).to.be.instanceOf(UnknownDependenciesException);
1743
});
1844
});

integration/injector/src/properties/properties.module.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Module } from '@nestjs/common';
22
import { DependencyService } from './dependency.service';
3-
import { PropertiesService } from './properties.service';
3+
import { PropertiesService, SYMBOL_TOKEN } from './properties.service';
44

55
@Module({
66
providers: [
@@ -10,6 +10,10 @@ import { PropertiesService } from './properties.service';
1010
provide: 'token',
1111
useValue: true,
1212
},
13+
{
14+
provide: SYMBOL_TOKEN,
15+
useValue: true,
16+
},
1317
],
1418
})
1519
export class PropertiesModule {}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
import { Inject, Injectable } from '@nestjs/common';
22
import { DependencyService } from './dependency.service';
33

4+
export const SYMBOL_TOKEN = Symbol('token');
5+
46
@Injectable()
57
export class PropertiesService {
68
@Inject() service: DependencyService;
79
@Inject('token') token: boolean;
10+
@Inject(SYMBOL_TOKEN) symbolToken: boolean;
811
}

packages/core/errors/messages.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { Module } from '../injector/module';
1010
* Returns the name of an instance
1111
* @param instance The instance which should get the name from
1212
*/
13-
const getInstanceName = (instance: unknown) =>
13+
const getInstanceName = (instance: unknown): string =>
1414
instance && (instance as Type<any>).name;
1515

1616
/**
@@ -19,13 +19,13 @@ const getInstanceName = (instance: unknown) =>
1919
* (= injection token). As fallback it returns '+'
2020
* @param dependency The dependency whichs name should get displayed
2121
*/
22-
const getDependencyName = (dependency: InjectorDependency) =>
22+
const getDependencyName = (dependency: InjectorDependency): string =>
2323
// use class name
2424
getInstanceName(dependency) ||
2525
// use injection token (symbol)
2626
(isSymbol(dependency) && dependency.toString()) ||
2727
// use string directly
28-
dependency ||
28+
(dependency as string) ||
2929
// otherwise
3030
'+';
3131

@@ -49,15 +49,16 @@ export const UNKNOWN_DEPENDENCIES_MESSAGE = (
4949
key,
5050
} = unknownDependencyContext;
5151
const moduleName = getModuleName(module) || 'Module';
52+
const dependencyName = getDependencyName(name);
5253

5354
let message = `Nest can't resolve dependencies of the ${type.toString()}`;
5455

5556
const potentialSolutions = `\n
5657
Potential solutions:
57-
- If ${name} is a provider, is it part of the current ${moduleName}?
58-
- If ${name} is exported from a separate @Module, is that module imported within ${moduleName}?
58+
- If ${dependencyName} is a provider, is it part of the current ${moduleName}?
59+
- If ${dependencyName} is exported from a separate @Module, is that module imported within ${moduleName}?
5960
@Module({
60-
imports: [ /* the Module containing ${name} */ ]
61+
imports: [ /* the Module containing ${dependencyName} */ ]
6162
})
6263
`;
6364

@@ -70,7 +71,7 @@ Potential solutions:
7071

7172
message += ` (`;
7273
message += dependenciesName.join(', ');
73-
message += `). Please make sure that the argument ${name} at index [${index}] is available in the ${getModuleName(
74+
message += `). Please make sure that the argument ${dependencyName} at index [${index}] is available in the ${getModuleName(
7475
module,
7576
)} context.`;
7677
message += potentialSolutions;

packages/core/injector/injector.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ export interface InjectorDependencyContext {
5555
/**
5656
* The name of the function or injection token
5757
*/
58-
name?: string;
58+
name?: string | symbol;
5959
/**
6060
* The index of the dependency which gets injected
6161
* from the dependencies array
@@ -411,7 +411,7 @@ export class Injector {
411411
}
412412

413413
public async lookupComponent<T = any>(
414-
providers: Map<string, InstanceWrapper>,
414+
providers: Map<string | symbol, InstanceWrapper>,
415415
module: Module,
416416
dependencyContext: InjectorDependencyContext,
417417
wrapper: InstanceWrapper<T>,

0 commit comments

Comments
 (0)