
在现代react应用开发中,测试api层面的交互是至关重要的一环。当涉及到graphql端点时,jest和msw(mock service worker)库是强大的组合,能够模拟网络请求,使测试更加独立和可控。然而,开发者在使用这套工具链时,常会遇到一些挑战,例如在jest环境中fetch函数未定义,或者msw未能成功拦截请求。本文将深入探讨这些问题,并提供一套完整的解决方案和最佳实践。
当你在Jest测试中遇到ReferenceError: fetch is not defined错误时,这通常是因为Jest的默认testEnvironment是node。在Node.js环境中,fetch API并非原生支持。为了解决这个问题,我们需要引入一个fetch的polyfill。
isomorphic-fetch是一个流行的polyfill,它在浏览器和Node.js环境中都提供了fetch的实现。
首先,安装isomorphic-fetch:
npm install --save-dev isomorphic-fetch # 或者 yarn add --dev isomorphic-fetch
然后,在Jest的设置文件(通常是setupTests.js或jest.setup.js)中导入它。这个文件会在每个测试文件运行前被执行。
setupTests.js:
import 'isomorphic-fetch'; // 引入 fetch polyfill
import { server } from './src/__mocks__/server';
// MSW 服务器生命周期管理
beforeAll(() => server.listen()); // 在所有测试开始前启动 MSW 服务器
afterEach(() => server.resetHandlers()); // 在每个测试后重置 MSW 处理器
afterAll(() => server.close()); // 在所有测试结束后关闭 MSW 服务器确保你的jestConfig.js或jest.config.js文件正确引用了setupTests.js。
jestConfig.js:
module.exports = {
transform: {
'^.+\.jsx?$': 'babel-jest',
},
watchPlugins: ['jest-watch-typeahead/filename', 'jest-watch-typeahead/testname'],
setupFilesAfterEnv: ['./setupTests.js'], // 确保此路径正确
// 如果使用TypeScript,可能需要配置 'preset': 'ts-jest/presets/js-with-ts'
// testEnvironment: 'jsdom', // 如果你的测试强烈依赖DOM环境,也可以考虑切换为jsdom
};通过以上配置,fetch函数将在你的Jest测试环境中可用,解决了“fetch is not defined”的问题。
即使fetch可用,MSW也可能无法拦截你的请求,这通常是由于Node.js环境中请求URL的特性以及GraphQL处理器匹配规则造成的。
确保你的MSW服务器和处理器定义正确。
src/__mocks__/server.js:
import { handlers } from "./handlers";
import { setupServer } from "msw/node"; // 专门用于 Node.js 环境
export const server = setupServer(...handlers);src/__mocks__/handlers.js:
import { graphql } from 'msw';
// 注意:这里我们直接使用 GraphQL 操作名称 'Favorites' 进行匹配
// 而不是完整的查询字符串。这是 MSW 推荐的 GraphQL 匹配方式。
export const handlers = [
graphql.query('Favorites', (req, res, ctx) => {
return res(
ctx.data({
favorites: [1], // 返回模拟数据
}),
);
}),
];在Node.js环境中,MSW对于fetch的拦截机制与浏览器环境有所不同。为了确保MSW能够可靠地拦截请求,你的fetch调用应使用一个绝对URL。此外,graphql.query处理器应使用GraphQL操作名称来匹配请求,而不是完整的查询字符串。
src/store/favorites/utils.js (更新后的fetchFavorites函数):
export const FAVORITES_QUERY = `
query Favorites { # 'Favorites' 是操作名称
favorites
}
`;
export async function fetchFavorites() {
// 在Node.js测试环境中,使用一个绝对URL,例如 'http://localhost/graphql'
// 或者任何有效的绝对URL,MSW会拦截它。
return fetch("http://example.com/graphql", { // 修改为绝对URL
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({ query: FAVORITES_QUERY })
})
.then((resp) => resp.json())
.then((result) => {
return result.data && result.data.favorites ? result.data.favorites : [];
})
.catch((err) => {
console.error("Error fetching favorites:", err);
return undefined;
});
}通过将fetch请求的URL从/graphql修改为http://example.com/graphql(或其他任何绝对URL),MSW在Node.js环境中就能正确识别并拦截它。同时,graphql.query('Favorites', ...)将精确匹配到query Favorites { ... }这样的GraphQL操作。
现在,所有必要的配置都已到位,我们可以编写一个可靠的测试用例来验证fetchFavorites函数。
src/store/favorites/__tests__/utils.test.js:
import { fetchFavorites } from '../utils';
describe('fetchFavorites', () => {
it('应该成功获取收藏列表', async () => {
const mockFavorites = [1];
// 调用 fetchFavorites,它将通过 MSW 拦截并返回模拟数据
const favorites = await fetchFavorites();
expect(favorites).toEqual(mockFavorites);
});
// 可以添加更多测试用例,例如测试错误情况
it('应该在请求失败时返回 undefined', async () => {
// 模拟一个错误响应
// server.use(
// graphql.query('Favorites', (req, res, ctx) => {
// return res(ctx.status(500));
// })
// );
// const favorites = await fetchFavorites();
// expect(favorites).toBeUndefined();
});
});在这个测试中,当fetchFavorites()被调用时,isomorphic-fetch提供的fetch函数将被执行。由于MSW服务器已启动并配置了相应的处理器,fetch请求会被MSW拦截,并返回handlers.js中定义的模拟数据[1],而不是尝试进行真实的网络请求。
通过本文的指导,你已经学会了如何解决在使用Jest和MSW测试React GraphQL应用时常见的两个核心问题:
遵循这些最佳实践,你将能够构建健壮、可靠的单元测试和集成测试,有效隔离API层逻辑,提高代码质量和开发效率。记住,清晰的错误处理和全面的测试覆盖是任何高质量应用不可或缺的部分。
以上就是高效测试React GraphQL应用:Jest与MSW集成实践指南的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号