2017-08-15 75 views
6

Używam react-apollo do zbudowania klienta, który zużywa interfejs API GraphQL, jednak utknąłem na testach. To, czego chcę, to kpić z serwera, aby móc łatwo przetestować aplikację bez konieczności wykonywania połączeń sieciowych.Jak używać wyśmianych danych z react-apollo do testów

Znalazłem kilka wskazówek, w jaki sposób mock serwera:

Ale tak naprawdę nie jest to przykład, w jaki sposób korzystać z tego serwera w szydzili moje testy aplikacji, aby uniknąć trafienia na serwer.

Moim celem jest testach integracyjnych setup twierdzić, że aplikacja jest rzeczywiście działa:

describe('Profile feature',() => { 
    beforeAll(() => { 
    store = setupStore(); 
    app = mount(
     <ApolloProvider store={store} client={apolloClient}> 
     <ConnectedRouter history={history}> 
      <App /> 
     </ConnectedRouter> 
     </ApolloProvider> 
    ); 
    }); 
}); 

Sklep korzysta Redux, a klient jest tworzony tak:

const networkInterface = createNetworkInterface({ 
    uri: process.env.REACT_APP_API_URL 
}); 

export const apolloClient = new ApolloClient({ 
    networkInterface 
}); 

Jak można Używam wyśmiewanego serwera z grafql-tools tutaj zamiast rzeczywistego API?

Odpowiedz

11

znalazłem 2 różne sposoby tworzenia szydzili danych dla zapytań Apollo-klient:

Pierwszym jest użycie graphql-tools stworzyć szydzili serwer oparty na schemacie backend, aby połączyć ten wyśmiewany serwer ze swoimi testami jest to możliwe, aby stworzyć mockNetworkInterface tak:

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); 
    } 
} 

Możesz przekazać ten interfejs sieciowy do komponentu ApolloClient i powinien działać dobrze!

Ta konfiguracja wymaga aktualnego schematu interfejsu API w kliencie, więc było mi trochę problemów.

Innym sposobem na osiągnięcie tego jest użycie mockNetworkInterface dostarczone przez apollo-client/test-utils

można użyć go w ten sposób:

import { UserMock, PublicationMock } from '../__mocks__/data'; 
import { mockNetworkInterface } from 'react-apollo/test-utils'; 
import ApolloClient from 'apollo-client'; 

// 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}`); 
    }); 
}); 

ważne jest, aby zdać addTypename: false do instancji ApolloClient, w przeciwnym razie trzeba będzie dodaj __typename do wszystkich zapytań ręcznie.

Można sprawdzać realizację mockNetworkInterface tutaj: https://github.com/apollographql/apollo-test-utils/blob/master/src/mocks/mockNetworkInterface.ts

+1

Dziękujemy za pytanie i odpowiedź! To postawiło mnie na właściwej drodze po wielu godzinach poszukiwań! –

+0

Cieszę się, że mogłem ci pomóc, zbyt długo się z tym zmagałem. –

+0

@CarlosMartinez, który z nich jest ogólnie przyjętą najlepszą praktyką lub najlepiej obsługiwaną biblioteką/opcją? – arcom

6

Można również użyć MockedProvider, co czyni go jeszcze prostsze.

withPersons.js

import { gql, graphql } from 'react-apollo' 

export const PERSONS_QUERY = gql` 
    query personsQuery { 
    persons { 
     name 
     city 
    } 
    } 
` 

export const withPersons = graphql(PERSONS_QUERY) 

withPersons.test.js

/* eslint-disable react/prop-types */ 

import React, { Component } from 'react' 
import { MockedProvider } from 'react-apollo/test-utils' 

import { withPersons, PERSONS_QUERY } from '../withPersons' 

it('withPersons', (done) => { 
    const mockedData = { 
    persons: [ 
     { 
     name: 'John', 
     city: 'Liverpool', 
     }, 
     { 
     name: 'Frank', 
     city: 'San Diego', 
     }, 
    ], 
    } 

    const variables = { cache: false } 

    class Dummy extends Component { 
    componentDidMount() { 
     const { loading, persons } = this.props.data 
     expect(loading).toBe(true) 
     expect(persons).toBe(undefined) 
    } 

    componentWillReceiveProps(nextProps) { 
     const { loading, persons } = nextProps.data 

     expect(loading).toBe(false) 
     expect(persons).toEqual(mockedData.persons) 
     done() 
    } 

    render() { 
     return null 
    } 
    } 
    const DummyWithPersons = withPersons(Dummy) 
    mount(
    <MockedProvider 
     removeTypename 
     mocks={[ 
     { 
      request: { query: PERSONS_QUERY, variables }, 
      result: { data: mockedData } }, 
     ]} 
    > 
     <DummyWithPersons /> 
    </MockedProvider>, 
) 
}) 

Uwaga: Przy użyciu manekina komponent po prostu przetestować zapytań graphql() i mutacje i sposób ich nie ustawił (opcje, rekwizyty, pomiń, zmiennych, itd.) Więc nie montażu komputera rzeczywiste składniki React. Lepiej przetestować tych w stanie "niepodłączonym".

+0

Tak, moj jedyny problem z MockedProvider polegał na tym, że nie mogłeś przekazać addTypename: false do bazowego klienta apollo, więc twoje mocks musiałby wszędzie zawierać __typename. Połączyli PR otworzyłem, aby naprawić ten https://github.com/apollographql/react-apollo/pull/1001 –

+0

Właściwie używasz rekwizytu, lol, miło –

+0

Och, widzę, to twoja prop! haha - zauważyłem to tylko dzisiaj – devboell