我正在撰寫一個玩具應用程式來了解有關無服務器框架和 AWS AppSync 等的更多資訊。我正在嘗試盡可能多地進行 TDD。我mock-apollo-client用來模擬ApolloClient,我遇到了一個問題。當嘗試撰寫測驗以確保傳遞給查詢的引數時,測驗總是回傳 401 Unauthorized 錯誤。似乎仍在呼叫真正的端點,因為當將有效值x-api-key添加到 ApolloClient 的實體化時,測驗會從 AppSync 服務器回傳實際值,而不是我期望的模擬值。我使用的是模擬,而不是間諜,所以我不期望真正的終點會被真正擊中。此外,當我添加有效x-api-key時,測驗失敗,因為該函式從未被呼叫。
api ? recipes ? Given a valid recipe id ? Should call query with the id as a param
expect(jest.fn()).toBeCalledTimes(expected)
Expected number of calls: 1
Received number of calls: 0
我預計測驗會失敗,因為當前沒有使用任何引數呼叫查詢,而是因為從未呼叫過模擬函式而失敗。
我究竟做錯了什么?
代碼檔案
import { ApolloClient, gql, InMemoryCache } from '@apollo/client';
const client = new ApolloClient({
uri: 'https://redacted.appsync-api.redacted.amazonaws.com/graphql',
headers: {
'x-api-key': 'key-redacted',
},
cache: new InMemoryCache(),
});
export const GET_RECIPE_QUERY = gql`
query {
getRecipe (title:"Lemon Cheese Cake") {
title,
ingredients{
name,
amount,
unit
},
steps
}
}
`;
const gqlQuery = (title) => {
return client
.query({
query: GET_RECIPE_QUERY,
variables : { title }
});
};
export const getRecipe = async (id) => {
const result = await gqlQuery(id);
return result.data.getRecipe;
};
測驗檔案
import { createMockClient } from 'mock-apollo-client';
import { GET_RECIPE_QUERY, getRecipe } from './recipes';
const mockRecipe = {
title: 'Luke\'s Chocolate Orange',
ingredients: [
{
name: 'Orange',
amount: 1,
},
{
name: 'Chocolate',
amount: 250,
unit: 'grams',
},
],
steps: [
'Peel orange',
'Open chocolate',
'Eat chocolate',
'Throw orange away',
],
};
const mockClient = createMockClient();
const queryHandler = jest.fn().mockResolvedValue({data: {recipe: mockRecipe}});
mockClient.setRequestHandler(GET_RECIPE_QUERY, queryHandler);
describe('api', () => {
describe('recipes', () => {
describe('Given a valid recipe id', () => {
it('Should call query with the id as a param', async () => {
const id = 'Luke\'s Chocolate Orange';
const result = await getRecipe(id);
expect(queryHandler).toBeCalledTimes(1);
expect(queryHandler).toBeCalledWith(id);
});
});
});
});
| 套餐 | 版本 |
|---|---|
| @apollo/客戶 | 3.5.10 |
| 圖形 | 16.3.0 |
| @testing-library/jest-dom | 5.16.2 |
| @測驗庫/反應 | 12.1.4 |
| @testing-library/用戶事件 | 13.5.0 |
| 笑話 | 27.5.1 |
| 模擬阿波羅客戶端 | 1.2.0 |
uj5u.com熱心網友回復:
mock-apollo-client總是使用 with ApolloProvider,這樣你就可以通過 React context Provider 將 mock apollo 客戶端傳遞給后代組件。
但是,您的代碼無法以這種方式將模擬 apollo 客戶端傳遞給組件。您的代碼直接從 Apollo 客戶端發起請求。我們需要攔截這些 GraphQL 請求。有幾種方法可以做到這一點,例如msw。但是,我將繼續使用該mock-apollo-client庫進行演示。
您需要模擬模塊ApolloClient的類。@apollo/client我們需要使用Mocking Partials,我們不想模擬從中匯出的其他東西@apollo/client。由于mock-apollo-client庫已經提供createMockClient了創建模擬 apollo 客戶端的功能,我們不需要自己模擬。
一個作業示例:
recipes.ts:
import { ApolloClient, gql, InMemoryCache } from '@apollo/client';
const client = new ApolloClient({
uri: 'https://redacted.appsync-api.redacted.amazonaws.com/graphql',
headers: {
'x-api-key': 'key-redacted',
},
cache: new InMemoryCache(),
});
export const GET_RECIPE_QUERY = gql`
query {
getRecipe(title: "Lemon Cheese Cake") {
title
ingredients {
name
amount
unit
}
steps
}
}
`;
const gqlQuery = (title) => {
return client.query({
query: GET_RECIPE_QUERY,
variables: { title },
});
};
export const getRecipe = async (id) => {
const result = await gqlQuery(id);
return result.data.getRecipe;
};
recipes.test.ts:
import { createMockClient } from 'mock-apollo-client';
const mockRecipe = {
title: "Luke's Chocolate Orange",
ingredients: [
{ name: 'Orange', amount: 1, unit: 'abc' },
{ name: 'Chocolate', amount: 250, unit: 'grams' },
],
steps: ['Peel orange', 'Open chocolate', 'Eat chocolate', 'Throw orange away'],
};
const mockClient = createMockClient();
describe('api', () => {
describe('recipes', () => {
describe('Given a valid recipe id', () => {
beforeEach(() => {
jest.resetModules();
});
it('Should call query with the id as a param', async () => {
jest.doMock('@apollo/client', () => {
return {
...jest.requireActual('@apollo/client'),
ApolloClient: jest.fn(() => mockClient),
};
});
const queryHandler = jest.fn().mockResolvedValue({ data: { getRecipe: mockRecipe } });
const { GET_RECIPE_QUERY, getRecipe } = require('./recipes');
mockClient.setRequestHandler(GET_RECIPE_QUERY, queryHandler);
const title = "Luke's Chocolate Orange";
const result = await getRecipe(title);
expect(result).toEqual(mockRecipe);
expect(queryHandler).toBeCalledWith({ title });
});
});
});
});
測驗結果:
PASS src/stackoverflow/71612556/recipes.test.ts
api
recipes
Given a valid recipe id
? Should call query with the id as a param (91 ms)
------------------------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
------------------------|---------|----------|---------|---------|-------------------
All files | 90.91 | 100 | 66.67 | 90.91 |
mocks | 75 | 100 | 0 | 75 |
handlers.js | 66.67 | 100 | 0 | 66.67 | 14
server.js | 100 | 100 | 100 | 100 |
stackoverflow/71612556 | 100 | 100 | 100 | 100 |
recipes.ts | 100 | 100 | 100 | 100 |
------------------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 2.775 s
你可以在這里找到源代碼
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/452779.html
