reactjs - Hur testas en funktion inuti useEffect med Jest och Enzyme?
Jag testar mina komponenter med jest och enzyme. Jag vill ladda min komponent när hela sidan är laddad, så jag använder load-händelsen inuti useEffect, här är min kod
const RatingsAndReviews = (props: RatingsAndReviewsProps) => {
const [pageLoaded, setPageLoaded] = useState<boolean>(false)
const handleLoad = () => {
if (document.readyState === 'complete') {
setTimeout(() => {
setPageLoaded(true)
}, 1500)
}
}
React.useEffect(() => {
window.addEventListener('load', handleLoad)
return () => {
window.removeEventListener('load', handleLoad)
}
}, [])
return (...some code)
}
Jag vill testa denna handleLoad-funktion men jag kan inte lista ut hur jag kan skicka denna mock-funktion till min komponent eftersom komponenten redan förväntar sig props och eftersom det är TypeScript kan jag inte skicka något annat än de obligatoriska props, här är mitt testfall
it('Should run handleLoad function onMount', ()=>{
jest.spyOn(React, 'useEffect').mockImplementation(f => f())
const handleLoad = jest.fn();
wrapper = mount(<RatingsAndReviews {...propObj} />)
expect(handleLoad).toHaveBeenCalled();
})
Jag får detta fel expect(jest.fn()).toHaveBeenCalled()
Expected number of calls: >= 1
Received number of calls: 0
Svar #1
Försök att inte mocka implementeringen av tredjepartsbiblioteksfunktionen, eftersom en felaktig mock-implementering kommer att förstöra dess funktionalitet. Till exempel, useEffect(effect) react hook kör inte bara effect-funktionen. Tänk på,
React skjuter upp körningen av
useEffecttills efter att webbläsaren har målat.
Hur hånar du det? Felaktig hån kommer att leda till oväntat beteende. Dina tester kan gå igenom baserat på felaktig hånimplementering, men koden kommer att misslyckas när den faktiskt körs. Därför är det bättre att inte håna tredjepartsbiblioteket. Självklart är detta inte absolut. Du kan håna funktionerna i tredjepartsbiblioteket om de är enkla och självständiga.
För React-komponenten bör vi göra svartboxtester som endast testar komponentens beteende och funktionalitet, inte implementeringen. Vi bör behandla komponenten som en enhet istället för funktionen inuti den.
Vi bör testa vad som renderas när pageLoaded-tillståndet ändras.
Händelsehanterarna som definieras inuti funktionskomponenten är privata, du kan inte komma åt dem utifrån (testkod). Så du kan inte anropa dem direkt. Istället bör du trigga dem via användarhändelser. load-händelsen för ditt fall.
t.ex.
index.tsx:
import React from 'react';
import { useEffect, useState } from 'react';
export const RatingsAndReviews = (props) => {
const [pageLoaded, setPageLoaded] = useState<boolean>(false);
console.log('pageLoaded: ', pageLoaded);
const handleLoad = () => {
if (document.readyState === 'complete') {
setTimeout(() => {
setPageLoaded(true);
}, 1500);
}
};
useEffect(() => {
window.addEventListener('load', handleLoad);
return () => {
window.removeEventListener('load', handleLoad);
};
}, []);
return <div>{pageLoaded ? 'loaded' : 'not loaded'}</div>;
};
index.test.tsx:
import { mount } from 'enzyme';
import React from 'react';
import { act } from 'react-dom/test-utils';
import { RatingsAndReviews } from '.';
describe('RatingsAndReviews', () => {
it('Should run handleLoad function onMount', () => {
jest.useFakeTimers();
const wrapper = mount(<RatingsAndReviews />);
window.dispatchEvent(new Event('load'));
expect(wrapper.text()).toBe('not loaded');
act(() => {
jest.advanceTimersByTime(1500);
});
expect(wrapper.text()).toBe('loaded');
});
});
Testresultat:
PASS stackoverflow/71953030/index.test.tsx (11.883 s)
RatingsAndReviews
✓ Should run handleLoad function onMount (47 ms)
console.log
pageLoaded: false
at RatingsAndReviews (stackoverflow/71953030/index.tsx:7:11)
console.log
pageLoaded: true
at RatingsAndReviews (stackoverflow/71953030/index.tsx:7:11)
-----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
-----------|---------|----------|---------|---------|-------------------
All files | 93.33 | 75 | 80 | 92.86 |
index.tsx | 93.33 | 75 | 80 | 92.86 | 19
-----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 13.575 s, estimated 14 s
paketversioner:
"enzyme": "^3.11.0",
"enzyme-adapter-react-16": "^1.15.5",
"react": "^16.14.0",
"react-dom": "^16.14.0",
"jest": "^26.6.3",
