Open bengry opened 1 week ago
That would make for a nice helper. Is there more to the example where mockedUser
is being returned from a resolver and part of a graphql query?
One thing that makes it difficult, and maybe this doesn't matter in your case, is that with resolver functions you aren't creating individual User
objects. Since first
and last
are individual resolver functions, if first
always returned "John".
The query:
{
users {
first
last
}
}
would return
{
"data": [
{ "first": "John", "last": "Smith" },
{ "first": "John", "last": "Johnson" },
]
}
That would look something like this:
import { setResolver } from 'graphql-mocks/resolver-map';
const createUserMockMiddleware = (hardcodedFirstName) => (resolverMap) => {
setResolver(resolverMap, ["User", "first"], () => hardcodedFirstName);
setResolver(resolverMap, ["User", "last"], () => faker.name());
}
If you wanted something less hardcoded and more representative of instances of users then decoupling the User
from the resolver function to something stateful is helpful. Using graphql-paper
comes in handy. This technique is better described in GraphQL Paper: Separation of Concrete and Derived Data. In this case the concrete data is first
and the derived (dynamic) is last
.
import { Paper } from "graphql-paper";
const paper = new Paper(graphqlSchema);
const userMiddleware = (resolverMap, { dependencies }) => {
setReference(resolverMap, ['User', 'first'], (parent, args, context, info) =>
// return a specific user based on some criteria
dependencies.paper.User.find((user) => user.id === args.id)?.name
);
setReference(resolverMap, ['User', 'last'], () => sinon.name());
};
const handler = new GraphQLHandler({
dependencies: {
graphqlSchema,
paper,
},
});
// if the `async`
beforeEach(async () => {
paper.mutate(({ create }) => {
// create as many specific Users as needed
create("User", { first: "John" });
create("User", { first: "Jessica" });
});
});
The last thing I'll add is that the default resolver for a field is to look at its parent and return the property that matches the field name, so if you have a schema like:
schema {
query: Query
}
type Query {
user: User
users: [User!]!
}
type User {
first: String
last: String
}
const createMockuser = (partial) => {
return {
last: sinon.name(),
...partial,
};
};
const resolverMap = {
Query: {
user: () => createMockUser({ first: "John" })
users: () => [createMockUser({ first: "Bob" }), createMockUser({ first: "Jessica" })]
}
};
This might be a simple way of doing what you're after.
I think GraphQL Paper: Separation of Concrete and Derived Data is probably the closest fit? Let me know if I'm missing something or if this isn't quite what you're after. It might be helpful to see the example as the assertion of mockedUser
involving the resolvers and/or query.
As detailed in this gist (also shared in https://github.com/graphql-mocks/graphql-mocks/issues/273), we're using
graphql-mocks
to create fake data for GQL requests.Sometimes though we want to create a semi-fake type. i.e. create a basic type ourselves (similar to what
DeepPartial<SomeGQLType>
would do in TypeScript), and letgraphql-mocks
fill in the rest of the stuff.Ideally something like:
Is such a thing possible? The entire mocking infrastructure already exists, but I'm not sure if there's a userland API for connecting the dots and creating this
createMockOf
function.