日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關咨詢
選擇下列產品馬上在線溝通
服務時間:8:30-17:00
你可能遇到了下面的問題
關閉右側工具欄

新聞中心

這里有您想知道的互聯(lián)網營銷解決方案
React團隊是如何測試并發(fā)特性的

大家好,我卡頌。

創(chuàng)新互聯(lián)公司長期為超過千家客戶提供的網站建設服務,團隊從業(yè)經驗10年,關注不同地域、不同群體,并針對不同對象提供差異化的產品和服務;打造開放共贏平臺,與合作伙伴共同營造健康的互聯(lián)網生態(tài)環(huán)境。為長陽企業(yè)提供專業(yè)的網站設計制作、成都網站建設,長陽網站改版等技術服務。擁有10多年豐富建站經驗和眾多成功案例,為您定制開發(fā)。

React18進入大家視野已經有一段時間了,不知道各位有沒有嘗試「并發(fā)特性」呢?

當啟用「并發(fā)特性」后,React會從「同步更新」變?yōu)椤府惒?、帶?yōu)先級、可中斷的更新」。

這也為編寫單元測試帶來了一些難度。

本文來聊聊React團隊如何測試并發(fā)特性。

遇到的困境

主要有兩個問題需要面對。

1. 如何表達渲染結果?

React可以對接不同宿主環(huán)境的渲染器,大家最熟悉的渲染器想必是ReactDOM,用于對接「瀏覽器」與「Node環(huán)境」(SSR)。

對于一些場景,可以用ReactDOM的輸出結果做測試。

比如,下面是使用ReactDOM的輸出結果測試「無狀態(tài)組件的渲染結果是否符合預期」(測試框架是jest):

it('should render stateless component', () => {
const el = document.createElement('div');
ReactDOM.render(, el);
expect(el.textContent).toBe('A');
});

這里有個不方便的地方 —— 這個用例依賴瀏覽器環(huán)境與DOM API(比如用到document.createElement)。

對于測試「React內部運行機制」這樣的場景,摻雜了宿主環(huán)境相關信息顯然會讓測試用例編寫起來更繁瑣。

2. 如何測試并發(fā)環(huán)境?

如果將上文的用例中ReactDOM.render改為ReactDOM.createRoot,那么用例就會失?。?/p>

// 之前
ReactDOM.render(, el);
expect(el.textContent).toBe('A');
// 之后
ReactDOM.createRoot(el).render();
expect(el.textContent).toBe('A');

這是因為在新的架構下,很多「同步更新」變成了「并發(fā)更新」,當render執(zhí)行后,頁面還沒完成渲染。

要讓上述用例成功,最簡單的修改方式是:

ReactDOM.createRoot(el).render();
setTimeout(() => {
// 異步獲取結果
expect(el.textContent).toBe('A');
})

如何優(yōu)雅的應對這種變化?

React的應對策略

接下來我們來看React團隊的應對方式。

首先來看第一個問題 —— 如何表達渲染結果?

既然ReactDOM渲染器對應瀏覽器、Node環(huán)境,ReactNative渲染器對應Native環(huán)境。

那能不能為測試「內部運行流程」專門開發(fā)一個渲染器呢?

答案是肯定的。

這個渲染器叫React-Noop-Renderer。

簡單的說,這個渲染器會渲染出純JS對象。

實現一個渲染器

React內部有個叫Reconciler的包,他會引用一些「操作宿主環(huán)境」的API。

比如如下方法用于「向容器中插入節(jié)點」:

function appendChildToContainer(child, container) {
// 具體實現
}

對于瀏覽器環(huán)境(ReactDOM),使用appendChild方法實現即可:

function appendChildToContainer(child, container) {
// 使用appendChild方法
container.appendChild(child);
}

打包工具(rollup)將Reconciler包與上述這類「針對瀏覽器環(huán)境的API」打包起來,就是ReactDOM包。

在React-Noop-Renderer中,與ReactDOM中的DOM節(jié)點對標的是如下數據結構:

const instance = {
id: instanceCounter++,
type: type,
children: [],
parent: -1,
props
};

注意其中的children字段,用于保存子節(jié)點。

所以appendChildToContainer方法在React-Noop-Renderer中可以實現的很簡單:

function appendChildToContainer(child, container) {
const index = container.children.indexOf(child);
if (index !== -1) {
container.children.splice(index, 1);
}
container.children.push(child);
};

打包工具將Reconciler包與上述這類「針對React-Noop的API」打包起來,就是React-Noop-Renderer包。

基于React-Noop-Renderer,可以完全脫離正常的宿主環(huán)境,測試Reconciler內部的邏輯。

接下來來看第二個問題。

如何測試并發(fā)環(huán)境?

「并發(fā)特性」再復雜,說到底也只是「各種異步執(zhí)行代碼的策略」,最終執(zhí)行策略的API不外乎setTimeout、setInterval、Promise等。

在jest中,可以模擬這些異步API,控制他們的執(zhí)行時機。

比如上面的異步代碼,在React中的測試用例會這么寫:

// 測試用例修改后:
await act(() => {
ReactDOM.createRoot(el).render();
})
expect(el.textContent).toBe('A');

act方法來自jest-react包,他的內部會執(zhí)行jest.runOnlyPendingTimers方法,讓所有等待中的計時器觸發(fā)回調。

比如如下代碼:

setTimeout(() => {
console.log('執(zhí)行')
}, 9999999)

執(zhí)行jest.runOnlyPendingTimers后會立刻打印「執(zhí)行」。

通過這種方式,人為控制React并發(fā)更新的速度,同時對框架代碼0侵入。

除此之外,用于驅動并發(fā)更新的Scheduler(調度器)模塊,本身也有一個針對測試的版本。

在這個版本中,開發(fā)者可以手動控制Scheduler的輸入、輸出。

比如,我想測試組件卸載時useEffect回調的執(zhí)行順序。

如下面代碼所示,其中Parent為掛載的「被測試組件」:

function Parent() {
useEffect(() => {
return () => Scheduler.unstable_yieldValue('Unmount parent');
});
return ;
}
function Child() {
useEffect(() => {
return () => Scheduler.unstable_yieldValue('Unmount child');
});
return 'Child';
}
await act(async () => {
root.render();
});

根據yieldValue的插入順序是否符合預期,就能確定useEffect的邏輯是否符合預期:

expect(Scheduler).toHaveYielded(['Unmount parent', 'Unmount child']);

總結

React中測試用例的編寫策略為:

可以用ReactDOM測的用例,一般結合ReactDOM與ReactTestUtils(瀏覽器環(huán)境的輔助方法)完成

需要把控中間過程的用例,使用Scheduler的測試包,用Scheduler.unstable_yieldValue記錄過程信息

脫離宿主環(huán)境,單獨測試React內部運行流程的,使用React-Noop-Renderer

測試并發(fā)下的場景,需要結合上述工具與jest-react一起使用

如果想深入學習下React中與測試相關的技巧,可以看下司徒正美老師的作品anu[1]。

這是個類React框架,但能跑通800+的React用例。里面實現了ReactTestUtils、React-Noop-Renderer的簡化版。


當前標題:React團隊是如何測試并發(fā)特性的
網站網址:http://www.5511xx.com/article/dhcijsh.html