用 Jest 模拟 ApolloClient 的 client.query 方法
Mocking ApolloClient's client.query method with Jest
2020 年 1 月 22 日更新
来自@slideshowp2 的解决方案是正确的,但由于此类型错误,我根本无法使其工作:
TypeError: Cannot read property 'query' of undefined
好吧,原来是我开玩笑的配置设置了 resetMocks: true
。在我删除它之后,测试确实通过了。 (虽然我不知道为什么)
原问题:
我需要使用 Apollo Client 在 React 组件外部的辅助函数中执行 graphql 查询,经过一些反复试验后,我采用了这种方法,它按预期工作:
setup.ts
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 throws
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(),
}))
...但是我看不到。
你没有正确模拟。正确的方法是:
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/Whosebug/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/Whosebug/59829676
2020 年 1 月 22 日更新
来自@slideshowp2 的解决方案是正确的,但由于此类型错误,我根本无法使其工作:
TypeError: Cannot read property 'query' of undefined
好吧,原来是我开玩笑的配置设置了 resetMocks: true
。在我删除它之后,测试确实通过了。 (虽然我不知道为什么)
原问题:
我需要使用 Apollo Client 在 React 组件外部的辅助函数中执行 graphql 查询,经过一些反复试验后,我采用了这种方法,它按预期工作:
setup.ts
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 throws
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(),
}))
...但是我看不到。
你没有正确模拟。正确的方法是:
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/Whosebug/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/Whosebug/59829676