当一个组件有多个useQuery时,Apollo的MockedProvider不起作用?



我有一个简单的Apollo设置。在这个CodeSandbox示例中,我使用的是MockedProvider,但live也可以使用:

https://codesandbox.io/s/winter-glitter-o8ug5?file=/src/App.js: 0 - 1164

import { ApolloClient, InMemoryCache } from "@apollo/client";
import { gql, useQuery, ApolloProvider } from "@apollo/client";
import { MockedProvider } from "@apollo/client/testing";
const client = new ApolloClient({
uri: "https://48p1r2roz4.sse.codesandbox.io",
cache: new InMemoryCache()
});
const EXCHANGE_RATES_1 = gql`
query GetExchangeRates {
rates(currency: "USD") {
rate
}
}
`;
const mocks = [
{
request: {
query: EXCHANGE_RATES_1
},
result: {
data: {
rates: [
{
__typename: "ExchangeRate",
rate: "123"
}
]
}
}
}
];
const MyComponent = () => {
const { data: data1, loading: loading1 } = useQuery(EXCHANGE_RATES_1);
if (loading1) return <p>Loading...</p>;
return (
<div>
<h1>{data1?.rates[0].rate}</h1>
</div>
);
};
const AppMocked = () => {
return (
<MockedProvider addTypename={false} mocks={mocks}>
<MyComponent />
</MockedProvider>
);
};
const AppLive = () => {
return (
<ApolloProvider client={client}>
<MyComponent />
</ApolloProvider>
);
};
export default AppMocked;

我需要在MyComponent中增加一个useQuery。我知道这是一个奇怪的例子,因为它应该只是一个查询,但它说明了我遇到的问题。

https://codesandbox.io/s/magical-dewdney-j451d?file=/src/App.js: 0 - 1630

import { ApolloClient, InMemoryCache } from "@apollo/client";
import { gql, useQuery, ApolloProvider } from "@apollo/client";
import { MockedProvider } from "@apollo/client/testing";
const client = new ApolloClient({
uri: "https://48p1r2roz4.sse.codesandbox.io",
cache: new InMemoryCache()
});
const EXCHANGE_RATES_1 = gql`
query GetExchangeRates {
rates(currency: "USD") {
rate
}
}
`;
const EXCHANGE_RATES_2 = gql`
query GetExchangeRates {
rates(currency: "USD") {
currency
}
}
`;
const mocks = [
{
request: {
query: EXCHANGE_RATES_1
},
result: {
data: {
rates: [
{
__typename: "ExchangeRate",
rate: "123"
}
]
}
}
},
{
request: {
query: EXCHANGE_RATES_2
},
result: {
data: {
rates: [
{
__typename: "ExchangeRate",
currency: "YOLO"
}
]
}
}
}
];
const MyComponent = () => {
const { data: data1, loading: loading1 } = useQuery(EXCHANGE_RATES_1);
const { data: data2, loading: loading2 } = useQuery(EXCHANGE_RATES_2);
if (loading1 || loading2) return <p>Loading...</p>;
return (
<div>
<h1>{data1?.rates[0].rate}</h1>
<h2>{data2?.rates[0].currency}</h2>
</div>
);
};
const AppMocked = () => {
return (
<MockedProvider addTypename={false} mocks={mocks}>
<MyComponent />
</MockedProvider>
);
};
const AppLive = () => {
return (
<ApolloProvider client={client}>
<MyComponent />
</ApolloProvider>
);
};
export default AppMocked;

实时版本工作正常,但模拟版本有一个空的H1。当我退出data1时,我可以看到它最初确实有数据,但在随后的渲染中变成"未定义">

我无法在文档中看到任何解释为什么mock不起作用的东西:https://www.apollographql.com/docs/react/development-testing/testing/

由于某些原因,在您的设置中,查询被调用了不止一次。

这会导致"没有更多的模拟响应"。当每个查询调用消耗一个模拟响应时,会在幕后产生错误(参见mockLink.ts)。
第一次调用查询时,它返回模拟数据,这就是您最初看到它的原因。但是下一个调用抛出一个错误并将数据设置为undefined

我找到了两个方法来解决这个问题:

选项1通过将fetch-policy设置为no-cache来禁用MockedProvider上的缓存:

<MockedProvider 
mocks={mocks} 
defaultOptions={{
watchQuery: { fetchPolicy: 'no-cache' },
query: { fetchPolicy: 'no-cache' },
}}
>
<MyComponent />
</MockedProvider>

选项2通过提供newData函数,允许模拟响应被多次使用:

const mocks = [
{
request: {
query: EXCHANGE_RATES_1
},
result: {
data: {
rates: [
{
__typename: "ExchangeRate",
rate: "123"
}
]
}
},
newData: () => ({
data: {
rates: [
{
__typename: "ExchangeRate",
rate: "123"
}
]
}
})
},
{
request: {
query: EXCHANGE_RATES_2
},
result: {
data: {
rates: [
{
__typename: "ExchangeRate",
currency: "YOLO"
}
]
}
},
newData: () => ({
data: {
rates: [
{
__typename: "ExchangeRate",
currency: "YOLO"
}
]
}
})
}
];

最新更新