Typecriptcript를 사용하여 API 호출을 수행하는 React Hook "useEffect"를 테스트하려면 어떻게 해야 하는가?
나는 Typecript와 새로운 React 후크를 사용하는 간단한 React 앱에 대한 jest-enzyme 테스트를 작성 중이다.
하지만, 실내에서 이루어지는 api 통화의 시뮬레이션을 제대로 할 수 없는 것 같다.useEffect
낚싯바늘을 달다
useEffect
api call을 만들고useState
"setData"와 함께 "data"로 표시한다.
그런 다음 개체 "데이터"가 해당 테이블 셀에 테이블로 매핑된다.
이것은 모의 api 반응과 효소 탑재로 태클하기 쉬워야 할 것 같은데 자꾸 사용하라고 하는 오류가 생긴다.act()
구성 요소 업데이트의 경우
나는 사용하려고 노력했다.act()
여러 가지 방법이지만 소용이 없었다.나는 교체해 보았다.axios
얄팍한 효소와 반응-시험-반응-반응-반응을 보이는 렌더로 말이야 하지만 아무 효과가 없는 것 같아
구성 요소:
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;
테스트:
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())
});
테이블 본체 섹션이 렌더링된 테이블의 html을 기록할 것으로 예상하며, 비동기식 및 다른 방법으로 조롱하려고 시도했다.axios
하지만 계속 표 머리말이나 메세지를 받고 있어에 대한 업데이트.SalesPlanTable
시험내부는 에 싸여있지 않았다.act(...).
나는 여러 시간 동안 해결책을 찾았지만 효과가 있는 것을 찾을 수 없어서 용기를 내서 여기에서 물어보기로 했다.
여기 두가지 문제가 있다.
비동기 호출 위치setData
setData
호출을 받다Promise
콜백
즉시Promise
확인, 대기 중인 콜백은 PromiseJobs 대기열에 대기한다.PromiseJobs 대기열에 있는 모든 보류 중인 작업은 현재 메시지가 완료된 후 다음 메시지가 시작되기 전에 실행된다.
이 경우 현재 실행 중인 메시지는 테스트이므로 테스트가 완료되기 전에Promise
콜백은 뛸 기회가 있고setData
테스트가 끝날 때까지 호출되지 않는다.
이런 것을 이용해서 고칠 수 있다.setImmediate
약속 잡스의 콜백 후에 출마할 기회가 있을 때까지 당신의 주장을 연기하는 것.
전화도 해야 할 것 같은데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();
});
});
경고:...에 대한 업데이트는 행동으로 포장되지 않았다. (...)
경고는 외부 구성 요소에 대한 상태 업데이트에 의해 트리거됨act
.
비동기 호출로 인해 함수에 의해 트리거되는 상태 변경은 항상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);
});
내가 더 많은 정보를 찾고 있을 때 나는 겨우 10시간 전에 열린 #2073호에서 이와 같은 행동에 대해 이야기하면서 우연히 알게 되었다.
위 테스트를 코멘트에 추가해 도움을 주었다.enzyme
devs가 그 문제를 해결하다.
해결책
효과가 있고 또 제거된다.test was not wrapped in act(...)
경고의
const waitForComponentToPaint = async (wrapper) => {
await act(async () => {
await new Promise(resolve => setTimeout(resolve, 0));
wrapper.update();
});
};
사용량:
it('should do something', () => {
const wrapper = mount(<MyComponent ... />);
await waitForComponentToPaint(wrapper);
expect(wrapper).toBlah...
})
덕분에...
edpark11이 자신의 답변에서 언급한 @Brian_Adams 이슈에서 제시한 해결책이다.
원본 게시물: https://github.com/enzymejs/enzyme/issues/2073#issuecomment-565736674
나는 보관을 위해 몇 가지 수정하여 여기에 그 게시물을 베꼈다.
'Programing' 카테고리의 다른 글
클릭 시 중첩된 JSON-Data 탐색 (0) | 2022.03.13 |
---|---|
파이톤 3의 로_input()과 인풋()의 차이점은 무엇일까. (0) | 2022.03.13 |
Vuetify에 특정 숫자 입력 구성 요소가 있는가? (0) | 2022.03.12 |
vuex를 이용한 vue 2 JS에서의 Axios 요격 (0) | 2022.03.12 |
이미지 경로를 BLOB reactive native로 변환 (0) | 2022.03.12 |