···11---
22title: Testing
33-order: 3
33+order: 4
44---
5566+67# Testing
88+99+When testing your components, you're likely going to want to check arguments and force different states for your components using Urql.
1010+1111+> **Note:** Examples demonstrate the _React hooks_ version of Urql being used but underlying patterns apply to all implementations.
1212+1313+## Mocking the client
1414+1515+For the most part, Urql's hooks are just adapters for talking to the Urql client.
1616+1717+The way in which they do this is by making calls to the client via context.
1818+1919+- `useQuery` calls `executeQuery`
2020+- `useMutation` calls `executeMutation`
2121+- `useSubscription` calls `executeSubscription`
2222+2323+Here's an example client mock being used while testing a component.
2424+2525+```tsx
2626+import { mount } from 'enzyme';
2727+import { Provider } from 'urql';
2828+import { MyComponent } from './MyComponent';
2929+3030+const mockClient = {
3131+ executeQuery: jest.fn(),
3232+ executeMutation: jest.fn(),
3333+ executeSubscription: jest.fn(),
3434+};
3535+3636+it('renders', () => {
3737+ const wrapper = mount(
3838+ <Provider value={mockClient}>
3939+ <MyComponent />
4040+ </Provider>
4141+ );
4242+});
4343+```
4444+4545+## Testing calls to the client
4646+4747+Once you have your mock setup, calls to the client can be tested.
4848+4949+```tsx
5050+it('skips the query', () => {
5151+ mount(
5252+ <Provider value={mockClient}>
5353+ <MyComponent skip={true} />
5454+ </Provider>
5555+ );
5656+ expect(mockClient.executeQuery).toBeCalledTimes(0);
5757+});
5858+```
5959+6060+Testing mutations and subscriptions also work in a similar fashion.
6161+6262+```tsx
6363+it('triggers a mutation', () => {
6464+ const wrapper = mount(
6565+ <Provider value={mockClient}>
6666+ <MyComponent />
6767+ </Provider>
6868+ );
6969+ const variables = {
7070+ name: 'Carla',
7171+ };
7272+7373+ wrapper
7474+ .find('input')
7575+ .simulate('change', { currentTarget: { value: variables.name } });
7676+ wrapper.find('button').simulate('click');
7777+7878+ expect(mockClient.executeMutation).toBeCalledTimes(1);
7979+ expect(mockClient.executeMutation).toBeCalledWith(
8080+ expect.objectContaining({ variables })
8181+ );
8282+});
8383+```
8484+8585+## Forcing states
8686+8787+For testing render output, or creating fixtures, you may want to force the state of your components.
8888+8989+### Fetching
9090+9191+Fetching states can be simulated by returning a stream which never returns. Wonka provides a utility for this, aptly called `never`.
9292+9393+Here's a fixture which stays in the _fetching_ state.
9494+9595+```tsx
9696+import { Provider } from 'urql';
9797+import { never } from 'wonka';
9898+import { MyComponent } from './MyComponent';
9999+100100+const fetchingState = {
101101+ executeQuery: () => never,
102102+};
103103+104104+export default (
105105+ <Provider value={fetchingState}>
106106+ <MyComponent />
107107+ </Provider>
108108+);
109109+```
110110+111111+### Response (success)
112112+113113+Response states are simulated by providing a stream which contains a network response. For single responses, Wonka's `fromValue` function can do this for us.
114114+115115+**Example snapshot test of response state**
116116+117117+```tsx
118118+const responseState = {
119119+ executeQuery: () =>
120120+ fromValue({
121121+ data: {
122122+ posts: [
123123+ { id: 1, title: 'Post title', content: 'This is a post' },
124124+ { id: 3, title: 'Final post', content: 'Final post here' },
125125+ ],
126126+ },
127127+ }),
128128+};
129129+130130+it('matches snapshot', () => {
131131+ const wrapper = mount(
132132+ <Provider value={responseState}>
133133+ <MyComponent />
134134+ </Provider>
135135+ );
136136+ expect(wrapper).toMatchSnapshot();
137137+});
138138+```
139139+140140+### Response (error)
141141+142142+Error responses are similar to success responses, only the value in the stream is changed.
143143+144144+```tsx
145145+import { Provider, CombinedError } from 'urql';
146146+147147+const errorState = {
148148+ executeQuery: () =>
149149+ fromValue({
150150+ error: new CombinedError({
151151+ networkError: Error('something went wrong!'),
152152+ }),
153153+ }),
154154+};
155155+```
156156+157157+### Handling multiple hooks
158158+159159+Returning different values for many `useQuery` calls can be done by introducing conditionals into the mocked client functions.
160160+161161+```tsx
162162+const mockClient = () => {
163163+ executeQuery: ({ query }) => {
164164+ if (query === GET_USERS) {
165165+ return fromValue(usersResponse);
166166+ }
167167+168168+ if (query === GET_POSTS) {
169169+ return fromValue(postsResponse);
170170+ }
171171+ };
172172+};
173173+```
174174+175175+## Simulating changes
176176+177177+Simulating multiple responses can be useful, particularly testing `useEffect` calls dependent on changing query responses.
178178+179179+For this, a _subject_ is the way to go. In short, it's a stream which you can push responses to. The `makeSubject` function from Wonka is what you'll want to use for this purpose.
180180+181181+Below is an example of simulating subsequent responses (such as a cache update/refetch) in a test.
182182+183183+```tsx
184184+import { mount } from 'enzyme';
185185+import { act } from 'react-dom/test-utils';
186186+import { Provider } from 'urql';
187187+import { makeSubject } from 'wonka';
188188+import { MyComponent } from './MyComponent';
189189+190190+const [stream, pushResponse] = makeSubject();
191191+192192+const mockedClient = {
193193+ executeQuery: () => stream,
194194+};
195195+196196+it('shows notification on updated data', () => {
197197+ const wrapper = mount(
198198+ <Provider value={mockedClient}>
199199+ <MyComponent />
200200+ </Provider>
201201+ );
202202+203203+ // First response
204204+ act(() => {
205205+ pushResponse({
206206+ data: {
207207+ posts: [{ id: 1, title: 'Post title', content: 'This is a post' }],
208208+ },
209209+ });
210210+ });
211211+ expect(wrapper.find('dialog').exists()).toBe(false);
212212+213213+ // Second response
214214+ act(() => {
215215+ pushResponse({
216216+ data: {
217217+ posts: [
218218+ { id: 1, title: 'Post title', content: 'This is a post' },
219219+ { id: 1, title: 'Post title', content: 'This is a post' },
220220+ ],
221221+ },
222222+ });
223223+ });
224224+ expect(wrapper.find('dialog').exists()).toBe(true);
225225+});
226226+```