logo
Published on

[React Testing] Jest와 svgr

Authors
  • avatar

    jangth

테스트 코드를 작성하던 중 svgr 컴포넌트를 사용하고 있는 컴포넌트에서 에러가 발생하였다.

console.error
    Warning: React.jsx: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: object.

해당 에러는 React가 컴포넌트를 렌더링할 때 예상치 못한 타입을 받았음을 말해주고 있다. svg 아이콘을 컴포넌트화 하여 사용할 수 있게 해주는 svgr을 사용중인데, svgr 컴포넌트를 svg태그로 변환할 수 없는 상황에서 발생한 것으로 보인다.

즉 RTL의 render함수는 리액트 컴포넌트를 node.js 객체인 jsDOM으로 변환해야 하는데 svgr 컴포넌트를 svg 태그로 변환할 수 없기 때문에 발생한 것으로 생각한다.

✅ 해결책

jest, RTL에서는 실제 아이콘이 렌더링되는지 UI를 직접적으로 확인하는 것이 아니기 때문에 svg 컴포넌트를 간단한 리액트 컴포넌트로 모킹하기만 하면된다.

  1. mocks/svg.js
import React from 'react';
// eslint-disable-next-line react/display-name
const SvgrMock = React.forwardRef((props, ref) => <span ref={ref} {...props} />);
export const ReactComponent = SvgrMock;
export default SvgrMock;

﹒왜 fowardRef 사용? svgr 라이브러리는 svg 아이콘을 리액트 컴포넌트처럼 사용하도록 설정해주는데, 이때 svg 컴포넌트가 ref를 props로 받을 수 있기 때문이다.

﹒export const ReactComponent = SvgrMock;와 export default SvgrMock; export와 export default를 모두 지원하기 위해서이다. 왜냐하면 프로젝트 내에서 svg 컴포넌트를 가져오는 방식이 다를 수 있는데, 테스트 코드에서는 모킹한 svg만 조회 또는 확인만 하면 되기 때문에 export, export default 등 내부적인 구현 방식에 의존하지 않도록 해야한다.

  1. jest config
//...
  moduleNameMapper: {
    '^.+\\.(svg)$': '<rootDir>/__mocks__/svg.js',
  },

mocks 폴더에 svg컴포넌트를 default로 export한 후 jest config에서 해당 svg 목 파일을 설정해 두면 svgr 컴포넌트를 포함하는 코드를 테스트할 때 "svgr 컴포넌트를 -> span 태그" 로 대체되어 테스트를 진행하게 된다.


✔️ 참고 사이트

https://stackoverflow.com/questions/63511683/testing-mocking-reactcomponent-svg-imports-with-jest

https://github.com/gregberge/svgr/issues/83#issuecomment-1196022120

https://react-svgr.com/docs/jest/