Closed alessbell closed 6 months ago
I love the idea, but one thing to consider is how this will scale for companies with huge company-wide schemas. For example, Indeed's schema at present contains over 7000 types and 24000 fields. If a developer were to download that and feed that into createMockSchema
I would expect it to be quite slow, especially if this were executed in a test setup function. In order for this to be performant I see two possible approaches.
createMockSchema
implementation would need implement it's own internal caching mechanism so that the full schema file does not need to be parsed each time.Without an elegant way to handle huge schemas I fear that developers will resort to hand rolling their own pruned versions of schemas for the purpose of testing, which will create the new problem of keeping those pruned schemas in sync with the real schema.
@qswitcher that's a great call out! I need to do some testing with much larger schemas - I suspect caching will allow us to achieve the performance we need, but a schema pruning utility is an interesting idea, too. Totally agree we need to avoid a scenario where developers are having to maintain their own condensed version of the schema - thanks for the feedback!
This is awesome, really excited to have first-party tools for this! I published a post about a similar approach back when we were introducing GraphQL at Stripe: https://www.freecodecamp.org/news/a-new-approach-to-mocking-graphql-data-1ef49de3d491/
Hey everyone 👋
Last week we released v3.10 with new experimental testing APIs! Please see the documentation for more information.
There's also a new pinned issue https://github.com/apollographql/apollo-client/issues/11817 where we'd love to hear your feedback. Looking forward to hearing about what's working well and what can be improved. Thanks!
Do you have any feedback for the maintainers? Please tell us by taking a one-minute survey. Your responses will help us understand Apollo Client usage and allow us to serve you better.
This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. For general questions, we recommend using StackOverflow or our discord server.
The status quo
In her GraphQL Conf 2023 talk "Sophisticated Schema Mocking", Stephanie Saunders from Coinbase outlined some challenges she and her team have encountered testing front-end applications that consume GraphQL data. (I recommend watching the whole talk!)
A common theme is the brittleness of tests that make use of static response mocks for individual operations. If you've written tests with Apollo Client's
MockedProvider
, you may have seen warnings logged when none of the remaining mocks can be matched, or when fields are missing when writing a result to the cache: maybe the query now includes some new fields, or variables have changed.MockedProvider
is a useful tool for unit tests—and it's not going anywhere! But, in addition to some limitations inherent to static response mocking, it also doesn't allow developers to test the link chain, code in your application's critical path. Our team has been thinking about complementary testing utilities, and today I'm sharing this RFC for an API I'm callingproxiedSchema
.proxiedSchema
1. Summary
proxiedSchema
will allow developers to take a schema-driven approach to testing by generating responses using mock resolvers with default values for scalar values. This tool can be used for integration tests that allow you to test your link chain, and can also be paired with tools like MSW.An initial version should support the following features:
2. Detailed Design
The tool I’m proposing would require a static schema and a set of default mock resolvers, and accept optional scalar mocks. Here’s an example of how we’d configure it before writing our tests:
Your testing setup can then either make use of a terminating
SchemaLink
directly configured via a customrender
function, which would take our proxied schema:Using a custom
fetch
implementationSince we'd like to enable testing of your entire link chain with minimal environment-specific alterations, we plan to provide a custom
fetch
implementation that would effectively turn your terminatingHttpLink
into aSchemaLink
. This will be provided viacontext
in your tests.Usage with e.g. Jest and Testing Library
In our tests, we can now render a component that issues any query and make assertions against the output based on either data supplied by our mock resolvers or our scalar defaults if no resolver is found.
Consider the following component:
Here's how we might test out
Dog
component usingproxiedSchema
:Usage with MSW
proxiedSchema
should be compatible with MSW'sgraphql.operation
API for "resolving any outgoing GraphQL operations against a mock GraphQL schema." I've been focusing on API design but will share an example as soon as I can spin one up.3. Drawbacks
Thinking in your GraphQL schema
While I’d argue schema-driven testing has advantages over static response mocking, there will be a learning curve for some users. Some developers may not be familiar with the schema of the API their app is consuming, and writing mock resolvers (as opposed to "thinking in response JSON") might feel strange at first. OTOH, this is a great opportunity to provide high quality documentation that teaches/reinforces core GraphQL concepts.
4. Alternatives
Instead of using an object proxy, we could use the “provider”-style approach, similar to the design of
MockedProvider
.I'd argue that exposing a way of interfacing with the schema in a declarative way via object proxy has a DX benefit over the provider approach: mocking is decoupled from component rendering, so mock resolvers can be updated throughout a single test. It also importantly decouples this testing approach from a React-specific API, allowing developers outside of the React community to write tests in this style.
5. Unresolved Questions
@defer
: What will support for features that use multipart over HTTP look like? With MSW?