[ ] Regression
[x ] Bug report
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead post your question on Stack Overflow.
REQUEST
scope providers are not instantiated by Test.createTestingModule(...).compile()
I'm not sure if this is a bug, or if REQUEST
scoped providers should be tested differently.
import { Injectable, Scope } from '@nestjs/common'
import { Test } from '@nestjs/testing'
@Injectable({
scope: Scope.REQUEST,
})
class RequestService {
public value: string
constructor() {
this.value = 'value'
}
}
describe('Testing module', () => {
let service: RequestService
beforeEach(async () => {
const module = await Test.createTestingModule({
providers: [RequestService],
}).compile()
service = module.get<RequestService>(RequestService)
})
it('instantiates request scoped providers', () => {
expect(service.value).toBeDefined()
})
})
To be able to unit test REQUEST
scope providers.
Nest version: 6.1.1
For Tooling issues:
- Node version: 10.14.2
- Platform: Mac
Others:
I have found one workaround, which is to force my providers to static scope in the test:
const module = await Test.createTestingModule({
providers: [{ provide: RequestService, useClass: RequestService }],
}).compile()
I'm having a similar issue with my transient provider. I'm sharing my findings that may help devs fix this issue. Thi bug isn't related only to the testing mechanism. I have confirmed that if you use:
const app = await NestFactory.create(AppModule);
const service = app.get(SomeTransientProvider);
Any providers that are injected in SomeTransientProvider constructor are undefined.
Now if you create another normal provider which injects SomeTransientProvider, using this works:
const service = app.get(NormalProviderThatInjectsTransientProvider);
Here all injections work correctly.
Let's track this here: https://github.com/nestjs/nest/issues/2049
@meweltman Life saver, been looking for this issue for a while - i couldn't figure it out.
Your workaround is this best solution at this point then, i assume ?
@appsolutegeek as far as I can tell, yes
Dear @meweltman ,
thank you for this issue and your solution. How can you do this, if you want to test a DynamicModule
?
For example, my test module init
part looks like this:
beforeAll(async () => {
const module = await Test.createTestingModule({
imports: [
MyDynamicModule.forRoot({
// ... configuration params here
}),
],
}).compile();
myDynamicService = module.get<MyService>(MyService);
});
The MyService
is a regular @Injectable()
service (i.e., it has the regular Scope.SINGLETON
), however, this service has another MyRequestService
injected, which is Scope.REQUEST
as it needs to access values from the Request
itself (i.e., behave different based on values of the request).
Through the Injection Scope Hierarchy, the MyService
should (automatically) be also Scope.REQUEST
) because it relies on a REQUEST
service.
All my tests pass until i add the MyRequestService
to the constructor of the MyService
- then it fails because the this.myRequestService
is undefined
(i.e., it cannot be created).
All the best and thanks a lot for your help
Oh yeah.. and it makes all other injected services / providers / ... useless as well, as they are now all undefined
..
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.
Most helpful comment
I have found one workaround, which is to force my providers to static scope in the test: