Professional Documents
Culture Documents
Sophisticated Schema Mocking
Sophisticated Schema Mocking
#GraphQLConf
(2.5 yrs)
IC => Engineering Manager (5 mo)
● Developer Experience Org (velocity and quality)
○ Customers == Coinbase Engineers
● Data Layer Team (full stack)
○ GraphQL Service and Schema
○ @cbhq/data-layer
■ Wrapper around our GraphQL client
● Developer Experience Org (velocity and quality)
○ Customers == Coinbase Engineers
● Data Layer Team (full stack)
○ GraphQL Service and Schema
○ @cbhq/data-layer
■ Wrapper around our GraphQL client
● Migration from REST to GraphQL
○ Defining tools and best practices
○ Biggest customer complaint:
■ Mocking GraphQL in tests (Unit/E2E)
import { useLazyLoadQuery } from '@cbhq/data-layer';
if (req.variables?.id === 2) {
testName = 'test-user-name-2';
}
return res(
ctx.data({
viewer: {
id: 'test-viewer-id',
userProperties: {
id: 'test-user-properties-id',
name: testName,
},
const server = createTestMockServiceWorker(...);
render(
<MockedProvider mocks={mocks} addTypename={false}>
<UserProperties />
</MockedProvider>
);
const mocks = [
{
request: {
query: UserPropertiesQuery,
variables: {
id: 42
}
},
result: {
data: {
viewer: {
id: 'test-viewer-id',
userProperties: {
id: 'test-user-properties-id',
name: 'test-user-name',
},
},
},
}
}
];
relayEnvironment.mock.queueOperationResolver((operation) => {
return MockPayloadGenerator.generate(operation);
});
const { viewer } = useLazyLoadQuery<UserPropertiesQuery>(
graphql`
query UserPropertiesQuery {
viewer {
userProperties {
name
regionFeatures {
isInUs
}
}
}
}
`,
{},
);
const { viewer } = useLazyLoadQuery<UserPropertiesQuery>(
graphql`
query UserPropertiesQuery {
viewer {
userProperties {
name
regionFeatures {
isInUs
}
createdAt
}
}
}
`,
{},
);
relayEnvironment.mock.queueOperationResolver((operation) => {
return MockPayloadGenerator.generate(operation);
});
● Recap - Common Issues
○ Nock
■ Static mocks
■ No easy access to query variables
○ MSW
■ Static mocks
■ No React Native support
■ Extra config
○ Apollo
■ Static mocks (even variables)
○ Relay
■ Dynamic mocks only return strings
■ Have to mock operations in order
What we need:
● No mocking required just to render
○ Adding queries/fields to a component does
not break everything
● Clear access to query variables
○ And all request data
● Test should be easy to set up, with very little code
import { faker } from '@faker-js/faker';
// custom scalars
Uuid: () => faker.datatype.uuid(),
Email: () => 'default.user@coinbase.com',
Date: () => '2022-11-12',
Time: () => '2022-11-12T16:06:15.442Z',
Decimal: () => '42.42',
Url: () => 'http://testUrl.com',
TickerSymbol: () => 'USD',
CountryCode: () => 'US',
Json: () => {},
Locale: () => 'en',
PhoneNumber: () => '4152564879',
return createGraphqlEnvironment({
. . .
interceptors: {
queryLevelMockerConfig: {
queryLevelMockerMiddleware: createQueryLevelMockerMiddleware({
schema,
mockEnums,
mockOverrides,
mockResolvers,
baseMocks,
debugOperations,
}),
},
},
});
it('renders', async () => {
expect(await findByTestId('user-properties')).toBeVisible();
});
return createGraphqlEnvironment({
. . .
interceptors: {
queryLevelMockerConfig: {
queryLevelMockerMiddleware: createQueryLevelMockerMiddleware({
schema,
mockEnums,
mockOverrides,
mockResolvers,
baseMocks,
debugOperations,
}),
},
},
});
const fieldLevelMockData = [
{
fieldOverride: [
{
path: 'viewer.userProperties.email',
value: 'mymockemail@test.com',
},
],
},
];
const fieldLevelMockData = [
{
fieldOverride: [
{
path: 'viewer.userProperties.city',
value: 'Denver',
},
],
},
];
Development
Sandbox
Development
Sandbox
Benefits of Sophisticated Schema Mocking:
● Automatically mock queries Thank You!
#GraphQLConf