Mat*_*erg 12 typescript jestjs enzyme axios react-hooks
我正在使用Typescript和新的React钩子为一个简单的React应用编写一些有趣的酶测试。
但是,我似乎无法正确模拟在useEffect挂钩内进行的api调用。
useEffect进行api调用,并useState使用“ setData” 更新状态“ data”。
然后将对象“数据”映射到表中与其对应的表单元格中。
似乎应该可以通过模拟的api响应和酶安装来轻松解决,但是我不断收到错误消息,告诉我act()用于组件更新。
我尝试了act()许多方法,但无济于事。我试过用axiosfetch 代替,并使用酶浅和react-test-library的渲染,但是似乎没有任何效果。
组件:
import axios from 'axios'
import React, { useEffect, useState } from 'react';
interface ISUB {
id: number;
mediaType: {
digital: boolean;
print: boolean;
};
monthlyPayment: {
digital: boolean;
print: boolean;
};
singleIssue: {
digital: boolean;
print: boolean;
};
subscription: {
digital: boolean;
print: boolean;
};
title: string;
}
interface IDATA extends Array<ISUB> {}
const initData: IDATA = [];
const SalesPlanTable = () => {
const [data, setData] = useState(initData);
useEffect(() => {
axios
.get(`/path/to/api`)
.then(res => {
setData(res.data.results);
})
.catch(error => console.log(error));
}, []);
const renderTableRows = () => {
return data.map((i: ISUB, k: number) => (
<tr key={k}>
<td>{i.id}</td>
<td>
{i.title}
</td>
<td>
{i.subscription.print}
{i.mediaType.digital}
</td>
<td>
{i.monthlyPayment.print}
{i.monthlyPayment.digital}
</td>
<td>
{i.singleIssue.print}
{i.singleIssue.digital}
</td>
<td>
<button>Submit</button>
</td>
</tr>
));
};
return (
<table>
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>MediaType</th>
<th>MonthlyPayment</th>
<th>SingleIssue</th>
<th/>
</tr>
</thead>
<tbody'>{renderTableRows()}</tbody>
</table>
);
};
export default SalesPlanTable;
Run Code Online (Sandbox Code Playgroud)
考试:
const response = {
data: {
results: [
{
id: 249,
mediaType: {
digital: true,
print: true
},
monthlyPayment: {
digital: true,
print: true
},
singleIssue: {
digital: true,
print: true
},
subscription: {
digital: true,
print: true
},
title: 'ELLE'
}
]
}
};
//after describe
it('should render a proper table data', () => {
const mock = new MockAdapter(axios);
mock.onGet('/path/to/api').reply(200, response.data);
act(() => {
component = mount(<SalesPlanTable />);
})
console.log(component.debug())
});
Run Code Online (Sandbox Code Playgroud)
我希望它记录与呈现的表体部分表的HTML,我尝试了一些异步和不同的方式来嘲笑axios,但我保持要么想起来的表头或消息:更新SalesPlanTable内部测试没有被包裹在act(...).我花了好几个小时寻找解决方案,但找不到任何可行的方法,因此我决定鼓起勇气,在这里问一下。
Bri*_*ams 12
这里有两个问题
setDatasetData在Promise回调中被调用。
只要一Promise做出决议,任何回调等待它在得到排队PromiseJobs队列。PromiseJobs队列中的所有挂起作业都在当前消息完成之后且下一个消息开始之前运行。
在这种情况下,当前正在运行的消息是你的测试,以便在测试完成之前Promise回调有机会运行,setData不叫,直到后您的测试完成。
您可以通过使用类似于setImmediate延迟断言的方式来解决此问题,直到PromiseJobs中的回调有机会运行之后。
看起来您还需要调用component.update()以使用新状态重新渲染组件。(我猜这是因为状态更改发生在之外,act因为没有任何方法可以将回调代码包装在中act。)
总之,工作测试如下所示:
it('should render a proper table data', done => {
const mock = new MockAdapter(axios);
mock.onGet('/path/to/api').reply(200, response.data);
const component = mount(<SalesPlanTable />);
setImmediate(() => {
component.update();
console.log(component.debug());
done();
});
});
Run Code Online (Sandbox Code Playgroud)
该警告是由发生在之外的组件状态更新触发的act。
由函数触发的异步调用setDatauseEffect引起的状态改变总是发生在act。
这是一个非常简单的测试,演示了此行为:
import React, { useState, useEffect } from 'react';
import { mount } from 'enzyme';
const SimpleComponent = () => {
const [data, setData] = useState('initial');
useEffect(() => {
setImmediate(() => setData('updated'));
}, []);
return (<div>{data}</div>);
};
test('SimpleComponent', done => {
const wrapper = mount(<SimpleComponent/>);
setImmediate(done);
});
Run Code Online (Sandbox Code Playgroud)
当我在寻找更多信息时,我偶然发现enzyme问题#2073在10个小时前就开始讨论这种行为。
我在评论中添加了上述测试,以帮助enzyme开发人员解决此问题。
它既有效又消除了警告test was not wrapped in act(...)。
const waitForComponentToPaint = async (wrapper) => {
await act(async () => {
await new Promise(resolve => setTimeout(resolve, 0));
wrapper.update();
});
};
Run Code Online (Sandbox Code Playgroud)
用法:
it('should do something', () => {
const wrapper = mount(<MyComponent ... />);
await waitForComponentToPaint(wrapper);
expect(wrapper).toBlah...
})
Run Code Online (Sandbox Code Playgroud)
这是edpark11在他的回答中提到的问题@Brian_Adams中建议的解决方法。
原帖:https://github.com/enzymejs/enzyme/issues/2073#issuecomment-565736674
为了存档,我将帖子复制到此处并进行了一些修改。
| 归档时间: |
|
| 查看次数: |
9041 次 |
| 最近记录: |