Мок собственного хука
В процессе написания юнит-тестов мне понадобилось создать мок хука, который я сама написала. Все варианты, которые я нашла (с использованием jest.mock) не работают
Хук:
import PropTypes from 'prop-types';
import {
sendRefreshRequest,
sendLogoutRequest,
sendLoginRequest
} from '../serverRequests';
const authContext = createContext();
function useProvideAuth() {
const [accessToken, setAccessToken] = useState('');
const [isAuthenticated, setAuthenticated] = useState(
accessToken ? true : false
);
useEffect(() => {
refreshToken();
}, []);
const login = async (loginCredentials) => {
const accessToken = await sendLoginRequest(loginCredentials);
if (accessToken) {
setAccessToken(accessToken);
setAuthenticated(true);
}
};
const logout = async () => {
setAccessToken(null);
setAuthenticated(false);
await sendLogoutRequest();
};
const refreshToken = async () => {
const accessToken = await sendRefreshRequest();
if (accessToken) {
setAccessToken(accessToken);
setAuthenticated(true);
} else setAuthenticated(false);
setTimeout(async () => {
refreshToken();
}, 15 * 60000 - 1000);
};
return {
isAuthenticated,
accessToken,
login,
logout
};
}
export function AuthProvider({ children }) {
const auth = useProvideAuth();
return <authContext.Provider value={auth}>{children}</authContext.Provider>;
}
AuthProvider.propTypes = {
children: PropTypes.any
};
const useAuth = () => {
return useContext(authContext);
};
export default useAuth;
Компонент, на который я пишу юнит-тест:
import React from 'react';
import { Navigate, useLocation } from 'react-router-dom';
import laptop from '../assets/laptop.png';
import Login from '../auth/login/login';
import useAuth from '../auth/useAuth';
import './mainPage.css';
function Main() {
const isAuthenticated = useAuth().isAuthenticated;
const location = useLocation();
if (isAuthenticated)
return <Navigate to='/user' replace state={{ from: location.pathname }} />;
return (
<div className='d-flex main'>
<img className='main' data-testid='img' src={laptop} />
<Login />
</div>
);
}
export default Main;
Сам тест:
describe('Main when !isAuthenticated', () => {
beforeEach(() => {
jest.mock('../auth/useAuth', () => {
const originalModule = jest.requireActual('../auth/useAuth');
return {
__esModule: true,
...originalModule,
default: () => ({
isAuthenticated: false,
login: jest.fn,
logout: jest.fn
})
};
});
});
afterEach(() => {
jest.resetModules();
});
it('renders without crashing', () => {
render(<Main />);
});
it('displays image and login form', () => {
render(<Main />);
const image = screen.getByRole('img');
const form = document.querySelector('[data-testid=loginForm]');
expect(image).toBeInTheDocument();
expect(form).toBeInTheDocument();
});
});
Ошибка: TypeError: Cannot read properties of undefined (reading 'isAuthenticated')
7 |
8 | function Main() {
> 9 | const isAuthenticated = useAuth().isAuthenticated;
| ^
10 | const location = useLocation();
11 |
12 | if (isAuthenticated)
at Main (src/main/mainPage.js:9:26)
at renderWithHooks (node_modules/react-dom/cjs/react-dom.development.js:14985:18)
at mountIndeterminateComponent (node_modules/react-dom/cjs/react-dom.development.js:17811:13)
at beginWork (node_modules/react-dom/cjs/react-dom.development.js:19049:16)
at HTMLUnknownElement.callCallback (node_modules/react-dom/cjs/react-dom.development.js:3945:14)
at HTMLUnknownElement.callTheUserObjectsOperation (node_modules/jsdom/lib/jsdom/living/generated/EventListener.js:26:30)
at innerInvokeEventListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:338:25)
at invokeEventListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:274:3)
at HTMLUnknownElementImpl._dispatch (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:221:9)
at HTMLUnknownElementImpl.dispatchEvent (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:94:17)
at HTMLUnknownElement.dispatchEvent (node_modules/jsdom/lib/jsdom/living/generated/EventTarget.js:231:34)
at Object.invokeGuardedCallbackDev (node_modules/react-dom/cjs/react-dom.development.js:3994:16)
at invokeGuardedCallback (node_modules/react-dom/cjs/react-dom.development.js:4056:31)
at beginWork$1 (node_modules/react-dom/cjs/react-dom.development.js:23964:7)
at performUnitOfWork (node_modules/react-dom/cjs/react-dom.development.js:22779:12)
at workLoopSync (node_modules/react-dom/cjs/react-dom.development.js:22707:5)
at renderRootSync (node_modules/react-dom/cjs/react-dom.development.js:22670:7)
at performSyncWorkOnRoot (node_modules/react-dom/cjs/react-dom.development.js:22293:18)
at scheduleUpdateOnFiber (node_modules/react-dom/cjs/react-dom.development.js:21881:7)
at updateContainer (node_modules/react-dom/cjs/react-dom.development.js:25482:3)
at node_modules/react-dom/cjs/react-dom.development.js:26021:7
at unbatchedUpdates (node_modules/react-dom/cjs/react-dom.development.js:22431:12)
at legacyRenderSubtreeIntoContainer (node_modules/react-dom/cjs/react-dom.development.js:26020:5)
at Object.render (node_modules/react-dom/cjs/react-dom.development.js:26103:10)
at node_modules/@testing-library/react/dist/pure.js:101:25
at batchedUpdates$1 (node_modules/react-dom/cjs/react-dom.development.js:22380:12)
at act (node_modules/react-dom/cjs/react-dom-test-utils.development.js:1042:14)
at render (node_modules/@testing-library/react/dist/pure.js:97:26)