【发布时间】:2017-12-12 17:47:19
【问题描述】:
我有以下(简化的)React 组件。
class SalesView extends Component<{}, State> {
state: State = {
salesData: null
};
componentDidMount() {
this.fetchSalesData();
}
render() {
if (this.state.salesData) {
return <SalesChart salesData={this.state.salesData} />;
} else {
return <p>Loading</p>;
}
}
async fetchSalesData() {
let data = await new SalesService().fetchSalesData();
this.setState({ salesData: data });
}
}
安装时,我从一个 API 中获取数据,该 API 已抽象到一个名为 SalesService 的类中。我想模拟这个类,对于 fetchSalesData 方法我想指定返回数据(在一个承诺中)。
这或多或少是我希望我的测试用例的样子:
- 预定义测试数据
- 导入销售视图
- 模拟销售服务
设置 mockSalesService 以返回一个承诺,该承诺在解决时返回预定义的测试数据
创建组件
- 等待
- 检查快照
测试 SalesChart 的外观不是这个问题的一部分,我希望使用 Enzyme 来解决这个问题。我一直在尝试很多东西来模拟这个异步调用,但我似乎无法正确地模拟它。我在网上找到了以下 Jest mocking 的示例,但它们似乎没有涵盖这个基本用法。
- Hackernoon: 不使用异步调用
- Wehkamp tech blog:不使用异步调用
- Agatha Krzywda:不使用异步调用
- GitConnected: 不使用带函数的类来模拟
- Jest tutorial An Async Example:不使用带函数的类来模拟
- Jest tutorial Testing Asynchronous Code: 不使用带函数的类来模拟
- SO question 43749845:我无法通过这种方式将 mock 连接到真正的实现
- 42638889:是使用依赖注入,我不是
- 46718663:没有展示实际的模拟类是如何实现的
我的问题是:
- 模拟类应该是什么样子的?
- 我应该把这个模拟类放在哪里?
- 我应该如何导入这个模拟类?
- 如何判断这个模拟类取代了真实类?
- 如何设置mock类的具体功能的mock实现?
- 如何在测试用例中等待 Promise 得到解决?
下面给出了我有一个不起作用的例子。测试运行程序崩溃,错误为throw err;,堆栈跟踪中的最后一行是at process._tickCallback (internal/process/next_tick.js:188:7)
# __tests__/SalesView-test.js
import React from 'react';
import SalesView from '../SalesView';
jest.mock('../SalesService');
const salesServiceMock = require('../SalesService').default;
const weekTestData = [];
test('SalesView shows chart after SalesService returns data', async () => {
salesServiceMock.fetchSalesData.mockImplementation(() => {
console.log('Mock is called');
return new Promise((resolve) => {
process.nextTick(() => resolve(weekTestData));
});
});
const wrapper = await shallow(<SalesView/>);
expect(wrapper).toMatchSnapshot();
});
【问题讨论】:
-
根据您进行 XHR 调用的方式,您可能需要查看 nock 或 axios-mock-adapter。
-
谢谢!模拟实际的 HTTP 调用很有趣,但我正在寻找一种方法来模拟我自己的具有异步功能的类。他们发出 HTTP 请求是一种特殊情况。
标签: javascript reactjs unit-testing asynchronous jestjs