I'm using react-apollo to build a client that consumes a GraphQL API, however, I'm very stuck on testing. What I want is to mock the server so I can easily test the application without needing to make network calls.
I've found some pointers on how to mock the server:
But there isn't really an example on how to use this mocked server in my app tests to avoid hitting the server.
My goal is to setup integration tests to assert that the app is actually working:
describe('Profile feature', () => {
beforeAll(() => {
store = setupStore();
app = mount(
<ApolloProvider store={store} client={apolloClient}>
<ConnectedRouter history={history}>
<App />
</ConnectedRouter>
</ApolloProvider>
);
});
});
The store is using Redux and the client is being created like this:
const networkInterface = createNetworkInterface({
uri: process.env.REACT_APP_API_URL
});
export const apolloClient = new ApolloClient({
networkInterface
});
How can I use a mocked server with graphql-tools here instead of the actual API?
I wrote up a blog post a while that might be helpful: http://blog.dideric.is/2018/03/18/Testing-apollo-containers/
Apollo has something called LinkSchema that makes the first approach Carlos mentioned a lot easier. It still takes some setup, but I think it's worth it. If you're creating responses manually, you have to worry a lot more about keeping your tests up to date/getting false positives when the schema changes and you haven't accounted for it in your code.
I found 2 different ways of creating mocked data for apollo-client queries:
The first is to use graphql-tools to create a mocked server based on your backend schema, in order to connect this mocked server with your tests it's possible to create a mockNetworkInterface like this:
const { mockServer } = require("graphql-tools");
const { print } = require("graphql/language/printer");
class MockNetworkInterface {
constructor(schema, mocks = {}) {
if (schema === undefined) {
throw new Error('Cannot create Mock Api without specifying a schema');
}
this.mockServer = mockServer(schema, mocks);
}
query(request) {
return this.mockServer.query(print(request.query), request.variables);
}
}
You can pass this network interface to the ApolloClient component and it should work just fine!
Having this setup requires to have your API schema up to date in your client, so I found it a bit of a pain to do.
Another way of doing this is using the mockNetworkInterface
provided by apollo-client/test-utils
You can use it this way:
import App from './App';
import { UserMock, PublicationMock } from '../__mocks__/data';
import { mockNetworkInterface } from 'react-apollo/test-utils';
import ApolloClient from 'apollo-client';
import { ApolloProvider } from 'react-apollo';
// We will be using here the exact same Query defined in our components
// We will provide a custom result or a custom error
const GraphQLMocks = [
{
request: {
query: UserProfileQuery,
variables: {}
},
result: {
data: {
current_user: UserMock
}
}
}
];
// To set it up we pass the mocks to the mockNetworkInterface
const setupTests = () => {
const networkInterface = mockNetworkInterface.apply(null, GraphQLMocks);
const client = new ApolloClient({ networkInterface, addTypename: false });
const wrapper = mount(
<ApolloProvider client={client}>
<App />
</ApolloProvider>
);
return {
store,
wrapper
};
};
// Then the tests look like this
describe('Profile feature', () => {
test('Profile view should render User details', async () => {
const { wrapper, store } = setupTests();
const waitFor = createWaitForElement('.profile');
await waitFor(wrapper);
const tag = wrapper.find('.profile-username');
expect(tag.text()).toEqual(`${UserMock.first_name} ${UserMock.last_name}`);
});
});
It is important to pass addTypename: false
to the ApolloClient
instance, otherwise you will need to add __typename
to all your queries manually.
You can inspect the implementation of the mockNetworkInterface here: https://github.com/apollographql/apollo-test-utils/blob/master/src/mocks/mockNetworkInterface.ts
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With