Documentation about "Testing request scoped instances" does not apply to GraphQL setups
I'm submitting a...
[ ] Regression
[ ] Bug report
[ ] Feature request
[x] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead post your question on Stack Overflow.
Current behavior
I was trying to do a GraphQL-based E2E spec with request scoped providers. To be able to resolve the same request-scoped provider instances in my test as they are used by nestjs when fulfilling the request, I followed https://docs.nestjs.com/fundamentals/testing#testing-request-scoped-instances. Unfortunately, I noticed that the suggested spyOn(ContextIdFactory, 'getByRequest') was never triggered. Digging into the source code, I found out that ContextIdFactory.getByRequest() is only called by Nest when using regular controllers (link to source code). When using @nestjs/graphql, the contextId is actually taken from gqlContext[REQUEST_CONTEXT_ID] || gqlContext.req[REQUEST_CONTEXT_ID] or created otherwise using createContextId() (link to source code).
Attaching my contextId to gqlContext[REQUEST_CONTEXT_ID] actually solved my issue.
Expected behavior
Since the "testing request scoped instances" headline is placed in the "fundamentals" section, I thought it would apply to all kind of NestJS specs, whether I use GraphQL or not. If this is intended, I would expect a hint that this approach does not work for graphql requests and some additional best practice / guideline about how to achieve this with graphql. As an alternative, maybe we could suggest setting request[REQUEST_CONTEXT_ID] directly instead of spying on ContextIdFactory.getByRequest. If I understood the source code correctly, this would work for both graphql and regular http requests.
@antoniusostermann - Could you please provide an example of a test that sets the contextId to the gqlContext (or the request)?
@sethew I guess you could ask this on https://discord.gg/nestjs
I've discovered the same and this is the workaround I'm using for now:
beforeEach(async () => {
//creating a contextId
const contextId = ContextIdFactory.create()
const moduleFixture: TestingModule = await Test.createTestingModule({
imports: [
///.... other modules imported here
GraphQLModule.forRoot<ApolloDriverConfig>({
driver: ApolloDriver,
context: ({ req }) => {
req[REQUEST_CONTEXT_ID] = contextId //adding the context id to the request object
return {
req: req,
}
},
}),
]
//rest of module definition
})
})