|
1 | | -import { InjectionToken, Provider, Scope } from '@nestjs/common'; |
| 1 | +import { InjectionToken, Provider, Scope, Injectable } from '@nestjs/common'; |
2 | 2 | import { expect } from 'chai'; |
3 | 3 | import * as sinon from 'sinon'; |
4 | 4 | import { setTimeout } from 'timers/promises'; |
@@ -375,4 +375,64 @@ describe('NestApplicationContext', () => { |
375 | 375 | }); |
376 | 376 | }); |
377 | 377 | }); |
| 378 | + |
| 379 | + describe('implicit request scope via enhancers', () => { |
| 380 | + it('get() should throw when dependency tree is not static (request-scoped enhancer attached)', async () => { |
| 381 | + class Host {} |
| 382 | + @Injectable({ scope: Scope.REQUEST }) |
| 383 | + class ReqScopedPipe {} |
| 384 | + |
| 385 | + const nestContainer = new NestContainer(); |
| 386 | + const injector = new Injector(); |
| 387 | + const instanceLoader = new InstanceLoader( |
| 388 | + nestContainer, |
| 389 | + injector, |
| 390 | + new GraphInspector(nestContainer), |
| 391 | + ); |
| 392 | + const { moduleRef } = (await nestContainer.addModule(class T {}, []))!; |
| 393 | + |
| 394 | + // Register Host as a controller (matches real-world controller case) |
| 395 | + nestContainer.addController(Host, moduleRef.token); |
| 396 | + |
| 397 | + // Register a request-scoped injectable and attach it as an enhancer to Host |
| 398 | + // This simulates a method-level pipe/guard/interceptor making Host implicitly request-scoped |
| 399 | + nestContainer.addInjectable(ReqScopedPipe, moduleRef.token, 'pipe', Host); |
| 400 | + |
| 401 | + const modules = nestContainer.getModules(); |
| 402 | + await instanceLoader.createInstancesOfDependencies(modules); |
| 403 | + |
| 404 | + const appCtx = new NestApplicationContext(nestContainer); |
| 405 | + |
| 406 | + // With a non-static dependency tree, get() should refuse and instruct to use resolve() |
| 407 | + expect(() => appCtx.get(Host)).to.throw(); |
| 408 | + }); |
| 409 | + |
| 410 | + it('resolve() should instantiate when dependency tree is not static (request-scoped enhancer attached)', async () => { |
| 411 | + class Host {} |
| 412 | + @Injectable({ scope: Scope.REQUEST }) |
| 413 | + class ReqScopedPipe {} |
| 414 | + |
| 415 | + const nestContainer = new NestContainer(); |
| 416 | + const injector = new Injector(); |
| 417 | + const instanceLoader = new InstanceLoader( |
| 418 | + nestContainer, |
| 419 | + injector, |
| 420 | + new GraphInspector(nestContainer), |
| 421 | + ); |
| 422 | + const { moduleRef } = (await nestContainer.addModule(class T {}, []))!; |
| 423 | + |
| 424 | + // Register Host as a controller |
| 425 | + nestContainer.addController(Host, moduleRef.token); |
| 426 | + |
| 427 | + nestContainer.addInjectable(ReqScopedPipe, moduleRef.token, 'pipe', Host); |
| 428 | + |
| 429 | + const modules = nestContainer.getModules(); |
| 430 | + await instanceLoader.createInstancesOfDependencies(modules); |
| 431 | + |
| 432 | + const appCtx = new NestApplicationContext(nestContainer); |
| 433 | + |
| 434 | + const instance = await appCtx.resolve(Host); |
| 435 | + expect(instance).instanceOf(Host); |
| 436 | + }); |
| 437 | + }); |
378 | 438 | }); |
0 commit comments