apollo-server: apollo-server-testing context is not receiving the `req` object
I am trying to write tests for header handling. I’m setting up the tests as follows:
it('should handle Accept-Language headers', async () => {
const acceptLanguage = 'sv, en';
const request = nock(config.API_URL)
.matchHeader('accept-language', acceptLanguage)
.get('/articles')
.reply(200, []);
const server = createServer();
const { query } = createTestClient(server);
await query({
query: '{ articles { id } }',
http: {
headers: { 'accept-language': acceptLanguage },
},
});
expect(request.isDone()).to.eql(true);
});
The test relies on the req
object being passed to the context
function in the server setup, but I’m only getting an empty object. Is this the expected behavior? If so, how do you go about writing tests for authentication headers etc?
Thanks!
About this issue
- Original URL
- State: closed
- Created 5 years ago
- Reactions: 68
- Comments: 39 (2 by maintainers)
Links to this issue
Commits related to this issue
- apollo-server-core: pass req obj to context when invoking executeOperation Fixes #2277. `apollo-server-testing` relies on `apollo-server-core` to execute queries for integration tests. However, `ap... — committed to vitorbal/apollo-server by vitorbal 5 years ago
- apollo-server-core: pass req obj to context when invoking executeOperation Fixes #2277. `apollo-server-testing` relies on `apollo-server-core` to execute queries for integration tests, via the `exec... — committed to vitorbal/apollo-server by vitorbal 5 years ago
- apollo-server-core: pass req obj to context when invoking executeOperation Fixes #2277. `apollo-server-testing` relies on `apollo-server-core` to execute queries for integration tests, via the `exec... — committed to vitorbal/apollo-server by vitorbal 5 years ago
- Add apollo-server-integration-testing dependency You can't really write real integration tests with apollo-server-testing, because it doesn't support servers which rely on the context option being a ... — committed to thebrutalcorporation/spensa by deduced 3 years ago
- Update user resolver tests to be more robust and have higher confidence Previously, the apollo-server-testing was used for the tests. This had key limitations, such as non-access to context without a... — committed to thebrutalcorporation/spensa by deduced 3 years ago
- Refactor transaction.test to use apollo-server-integration-testing dependency https://github.com/zapier/apollo-server-integration-testing since it allows for high confidence testing. The problems wit... — committed to thebrutalcorporation/spensa by deduced 3 years ago
I just ran into this.
I don’t consider it a true integration test unless you can actually test how your server’s true context is constructed. To hide behind a mock context doesn’t actually test anything.
I tried some of the solutions listed here and none of them worked for me. I ended up creating a new package that mimics the
apollo-server-testing
API, but allows for passing in a mockreq
object (or sets one for you automatically, with sensible defaults):https://github.com/zapier/apollo-server-integration-testing
We’ve been using it successfully at my company for the last 6 months to write real integration tests. Posting it here in case anyone else is interested in giving it a try 😃
I’ve been facing a similar issue.
I’ve implemented a token-based authentication. The server checks that a valid token is sent in a header and then it passes the token in the context to the resolvers. When i’m making tests there is no sense in setting a test-token and mocking the token-validating function because that is what I want to test. It would be very useful to have tests that ensure that this part of the code is working correctly, doing something like this:
Experiencing this and it’s making it impossible to write proper integration tests for logged in users etc.,
Edit: well, from the examples it seems like you are supposed to basically return a fixture from the server instance context, but I don’t think this is ideal.
I want to be able to test how my app integrates with apollo server, how can this be done properly if the behaviour of the apollo server when writing tests is different to what it will be like in production?
Hi, is there a proper solution atm? It is crazy that there is no supported way to pass custom headers to the req.
Are there any plans to solve this as part of the official testing package?
As others have already pointed out, not being able to mock out the
req
parameter on the context means that you cannot currently useapollo-server-testing
to do true integration testing.in typescript, context is private 🤕
here are two solutions i came up with:
if you are comfortable “polluting” the prototype the prototype will only be modified when using this testServer. will not impact your actual server.
“cleaner” solution with a subclass
usage for either approach
apollo-server-testing
is a pretty thin wrapper aroundexecuteOperation
, which is basically a method that lets you execute a GraphQL operation without going through the HTTP layer.We’re currently figuring out what parts of Apollo Server are really essential and which could be pared down in the upcoming AS3. My instincts are that
apollo-server-testing
doesn’t provide a huge amount of standalone value, and that we should document the direct use ofexecuteOperation
for tests that don’t want to test things that require the HTTP layer (like headers and cookies), and that we should encourage folks to use https://github.com/zapier/apollo-server-integration-testing for tests that require the HTTP layer (at least if you’re using Express!). I’m tracking this in #4952.I don’t think it’s likely that we’ll change the existing
apollo-server-testing
to work differently during v2 (ie, we’re probably not going to add anything Express-specific to it), so I’m going to close this issue. It’s great to see that there are so many approaches to doing these tests, includingapollo-server-integration-testing
!I found a much simpler solution to set the initial context arguments. What it does is that it wraps the context function with another function that “injects” the context argument:
Usage:
If you need to set custom context arguments per query or mutate, it can be further extended to be something like this:
Usage:
Hope this helps 😃
I know there are many solutions here already, but for some reason they weren’t sitting well with me. I made a very thin wrapper around
createTestClient
that does perfectly for me. Maybe it’ll help someone else, too 😃And instead of
import { createTestClient } from 'apollo-server-testing'
, just do aimport createTestClient from 'path/to/this/module'
. Enjoy!@liyikun 😢 well that sucks lol
Sent with GitHawk
Thanks for the heads up @dipiash, I faced this last week myself, I’ve updated the gist as well
Hello, @preetjdp!
Last few days I try to update dependencies for apollo-server. I have some problems with integration tests. And I found your solution and try.
I think that line 142 is incorrect https://gist.github.com/preetjdp/178643c5854ae775b005834be6687edc#file-createtestclient-ts-L142
If I start test with query:
I have the incorrect error:
But if I change line 142 on (I’m forked your gist https://gist.github.com/dipiash/bf69150518baf8ddb9b0e136fdf3c9d0#file-createtestclient-ts-L142):
I have correct result.
The following code worked for me.
@KristianWEB this has also helped us with our ApolloServer testing. Thank you!
Nice, thank you @KristianWEB
@FrancescoSaverioZuppichini I’ve implemented a custom testClient. Check it out
Unfortunately,
apollo-server-testing
doesn’t work when you need to work with req and res objects in the server side. Also none of the solutions really worked out for me becausereq
andres
are still mocks created manually by developers. As a result, when you do something likeres.cookie(...)
in your express server side, you’ll have an error because the mock res object doesn’t have something likecookie
function.I had to resort to using a graphql client created from
apollo-boost
and making real graphql requests to do integration testing.I found a solution through supertest
Apologies for recommending other package, but it is from the same ecosystem, not the competing one. I hope it is not displeasing the authors.
Since I could not find any pleasant solution, I have ended up writing tests using
apollo-boost
:I am not really sure if this is still called “integration testing” and not “e2e” but it works really for me. Thought this might come handy to someone still struggling.
Here is the gist of the approach I mentioned yesterday. This is a module that creates and exports a singleton test client. This assumes you’re using Jest, and that your context factory is in its own module. I think the paths are self explanatory but feel free to ask if anything isn’t clear.
You could probably modify this to be a test client builder rather than a singleton which would be a little safer so you don’t have to worry about maintaining token state between tests.
In case the context factory isn’t clear, the idea is that your ApolloServer is instantiated like so:
… and the context.js file is like:
Hope this helps someone.