首页 > 解决方案 > 在快照测试中模拟 React 子组件

问题描述

让我们假设有一个名为“HugeComponent”的非常大的组件及其快照测试。该组件在其他 N 个组件中使用。

例如:

import React from 'react';
import HugeComponent from './huge-component/HugeComponent';

const FirstComponent = () => {
  return (
    <div className="container">
      <h1>My First Component</h1>
      <p>This component renders a huge component</p>
      <HugeComponent />
    </div>
  );
};

const SecondComponent = () => {
  return (
    <div className="container">
       // … 
      <HugeComponent />
    </div>
  );
};

...

const NthComponent = () => {
  return (
    <div className="container">
       // … 
      <HugeComponent />
    </div>
  );
};

在几个快照测试教程中,我注意到子组件被模拟,以避免有大的快照。

所以相关的测试可能是这样的:

import React from 'react';
import { create } from 'react-test-renderer';
import MyFirstComponent from './MyFirstComponent';

jest.mock('../huge-component/HugeComponent', () => () => '<HugeComponent/>');

describe('MyFirstComponent', () => {
  it('should renders correctly', () => {
    const tree = create(<MyFirstComponent />);
    expect(tree.toJSON().toMatchSnapshot());
  });
});

// The tests for the other components are similar ...

现在让我们假设 HugeComponent 的实现发生了变化。此更改会破坏 HugeComponent 快照测试,但不会破坏 ui 也会更改的其他测试。

因此,如果我们进行快照测试以检测组件 ui 更改,为什么我们要模拟子组件,这可能会发生变化,从而使呈现它们的组件与起始组件不同?

编辑:让我们假设这个 HugeComponent 的初始实现:

import React from 'react';

const HugeComponent = () => {
  return (
    <div style={{ display: 'flex', justifyContent: 'center' }}>
      <img src="https://picsum.photos/200/300" alt="first" />
      <img src="https://picsum.photos/200/300" alt="second" />
      <img src="https://picsum.photos/200/300" alt="third" />
    </div>
  );
};

export default HugeComponent;

这是 MyFirstComponent 的相关快照(未应用模拟)

exports[FirstComponent should renders correctly 1] = 
<div
  className="container"
>
  <h1>
    My First Component
  </h1>
  <p>
    This component renders a huge component
  </p>
  <div
    style={
      Object {
        "display": "flex",
        "justifyContent": "center",
      }
    }
  >
    <img
      alt="first"
      src="https://picsum.photos/200/300"
    />
    <img
      alt="second"
      src="https://picsum.photos/200/300"
    />
    <img
      alt="third"
      src="https://picsum.photos/200/300"
    />
  </div>
</div>
;

现在让我们假设 HugeComponent 以这种方式改变:

import React from 'react';

const HugeComponent = () => {
  return (
    <div
      style={{
        display: 'flex',
        flexDirection: 'column',
        justifyContent: 'center',
      }}
    >
      <img src="https://picsum.photos/200/300" alt="first" />
      <img src="https://picsum.photos/200/300" alt="second" />
      <img src="https://picsum.photos/200/300" alt="third" />
    </div>
  );
};

export default HugeComponent;

所以 MyFirstComponent 的相关快照变成了:

exports[FirstComponent should renders correctly 1] = 
<div
  className="container"
>
  <h1>
    My First Component
  </h1>
  <p>
    This component renders a huge component
  </p>
  <div
    style={
      Object {
        "display": "flex",
        "flexDirection": "column",
        "justifyContent": "center",
      }
    }
  >
    <img
      alt="first"
      src="https://picsum.photos/200/300"
    />
    <img
      alt="second"
      src="https://picsum.photos/200/300"
    />
    <img
      alt="third"
      src="https://picsum.photos/200/300"
    />
  </div>
</div>
;

当 HugeComponent 发生变化时,MyFirstComponent ui 也会发生变化。

现在,如果我模拟 HugeComponent,与 MyFirstComponent 相关的测试不会检测到这种变化,即使我有两个不同的组件。

标签: javascriptreactjsjestjsmockingsnapshot

解决方案


推荐阅读