unit-testing - 用 Jest 模拟 ApolloClient 的 client.query 方法

标签 unit-testing mocking graphql jestjs apollo-client

2020 年 1 月 22 日更新

@slideshowp2 的解决方案是正确的,但由于此 TypeError,我根本无法使其正常工作:

TypeError: Cannot read property 'query' of undefined



好吧,原来是我的 Jest 配置具有 resetMocks: true放。在我删除它之后,测试确实通过了。 (虽然我不知道为什么)

原问题:

我需要使用 Apollo Client 在 React 组件之外的辅助函数中执行 graphql 查询,经过一些反复试验后,我采用了这种方法,该方法按预期工作:

设置文件

export const setupApi = (): ApolloClient<any> => {
  setupServiceApi(API_CONFIG)
  return createServiceApolloClient({ uri: `${API_HOST}${API_PATH}` })
}

getAssetIdFromService.ts

import { setupApi } from '../api/setup'

const client = setupApi()

export const GET_ASSET_ID = gql`
  query getAssetByExternalId($externalId: String!) {
    assetId: getAssetId(externalId: $externalId) {
      id
    }
  }
`

export const getAssetIdFromService = async (externalId: string) => {
  return await client.query({
    query: GET_ASSET_ID,
    variables: { externalId },
  })

  return { data, errors, loading }
}

现在我正在尝试为 getAssetIdFromService 编写测试测试。函数,但我无法弄清楚如何获得 client.query在测试中工作的方法。

我已经尝试了下面的方法,包括许多其他不起作用的方法。
对于这个特定的设置,jest 抛出

TypeError: client.query is not a function



import { setupApi } from '../../api/setup'
import { getAssetIdFromService } from '../getAssetIdFromService'

jest.mock('../../api/setup', () => ({
  setupApi: () => jest.fn(),
}))

describe('getAssetIdFromService', () => {
  it('returns an assetId when passed an externalId and the asset exists in the service', async () => {
    const { data, errors, loading } = await getAssetIdFromService('e1')

    // Do assertions  
  })
}

我想我遗漏了与这部分相关的内容:
jest.mock('../../api/setup', () => ({
  setupApi: () => jest.fn(),
}))

……但我看不到。

最佳答案

你没有正确地 mock 。这是正确的方法:
getAssetIdFromService.ts :

import { setupApi } from './setup';
import { gql } from 'apollo-server';

const client = setupApi();

export const GET_ASSET_ID = gql`
  query getAssetByExternalId($externalId: String!) {
    assetId: getAssetId(externalId: $externalId) {
      id
    }
  }
`;

export const getAssetIdFromService = async (externalId: string) => {
  return await client.query({
    query: GET_ASSET_ID,
    variables: { externalId },
  });
};
setup.ts :

export const setupApi = (): any => {};
getAssetIdFromService.test.ts :

import { getAssetIdFromService, GET_ASSET_ID } from './getAssetIdFromService';
import { setupApi } from './setup';

jest.mock('./setup.ts', () => {
  const mApolloClient = { query: jest.fn() };
  return { setupApi: jest.fn(() => mApolloClient) };
});

describe('59829676', () => {
  it('should query and return data', async () => {
    const client = setupApi();
    const mGraphQLResponse = { data: {}, loading: false, errors: [] };
    client.query.mockResolvedValueOnce(mGraphQLResponse);
    const { data, loading, errors } = await getAssetIdFromService('e1');
    expect(client.query).toBeCalledWith({ query: GET_ASSET_ID, variables: { externalId: 'e1' } });
    expect(data).toEqual({});
    expect(loading).toBeFalsy();
    expect(errors).toEqual([]);
  });
});

100% 覆盖率的单元测试结果:

 PASS   apollo-graphql-tutorial  src/stackoverflow/59829676/getAssetIdFromService.test.ts (8.161s)
  59829676
    ✓ should query and return data (7ms)

--------------------------|----------|----------|----------|----------|-------------------|
File                      |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
--------------------------|----------|----------|----------|----------|-------------------|
All files                 |      100 |      100 |      100 |      100 |                   |
 getAssetIdFromService.ts |      100 |      100 |      100 |      100 |                   |
--------------------------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        8.479s

源代码:https://github.com/mrdulin/apollo-graphql-tutorial/tree/master/src/stackoverflow/59829676

关于unit-testing - 用 Jest 模拟 ApolloClient 的 client.query 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59829676/

相关文章:

c# - 在 RhinoMocks 中模拟 void 函数的正确方法是什么?

node.js - 在测试中模拟对外部服务的 axios 请求

java - 如何创建自定义 SSLSocketFactory?

java - GraphQL Java 客户端库

javascript - 如何将 afterEach 与 Mocha 异步单元测试一起使用?

c# - 测试通用接口(interface)时出现奇怪的接口(interface)/TContext 错误

reactjs - 将参数传递给 react-apollo-hooks useQuery

time-series - 时间序列的 GraphQL

c# - 如何对嵌套的 foreach 循环进行单元测试?

iphone - 在xCode中引用来自不同目标的类以进行iPhone单元测试