You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Jest和Enzyme测试含document.getElementByClassName的React componentDidMount

React 16 + Jest/Enzyme 测试 componentDidMount 按钮样式修改失败的解决建议

问题背景

组件的componentDidMount逻辑中直接操作真实DOM修改按钮样式:

componentDidMount() {
if (this.props.isSubmissionComplete) {
  window.location.href = process.env.REACT_APP_BASE_PATH;
}

if (document.getElementsByClassName("continue-button")[0]) {
  document
    .getElementsByClassName("continue-button")[0]
    .classList.add("hidden");
}
if (document.getElementsByClassName("back-button")[0]) {
  document
    .getElementsByClassName("back-button")[0]
    .classList.remove("offset-sm-1");
}

//Sets the applicable coverages to the state for use in the post submission pages
var coverageList = this.renderCoverageList();
this.props.updateApplicableCoverages(coverageList);
}

测试用例尝试通过Enzyme检查样式,但断言失败:

let wrapper;

beforeEach(() => {
  wrapper = mount(
    <FraudStatement/>
  );
});

it("should hide the continue button if it exists", () => {
expect(wrapper.find(".continue-button").hasClass("hidden")).toBe(true);
});

错误信息:

Error: expect(received).toBe(expected) // Object.is equality

Expected: true
Received: false Jest

解决建议

1. 问题核心:DOM操作的上下文不一致

你的测试用例通过Enzyme的wrapper检查虚拟DOM,但组件逻辑直接操作真实浏览器DOM,两者状态不同步,导致Enzyme无法捕捉到样式变化。

2. 推荐修复:改用React数据流控制样式(符合React设计模式)

放弃直接操作DOM,改用组件状态或Props控制样式,让渲染逻辑完全由React管理:

// 组件内部修改
state = {
  shouldHideContinueBtn: false
};

componentDidMount() {
  // ...其他逻辑
  this.setState({ shouldHideContinueBtn: true });
}

render() {
  return (
    <button 
      className={`continue-button ${this.state.shouldHideContinueBtn ? 'hidden' : ''}`}
    >
      Continue
    </button>
  );
}

对应的测试用例可以直接检查Enzyme虚拟DOM的类名:

it("should hide the continue button after mount", () => {
  expect(wrapper.find(".continue-button").hasClass("hidden")).toBe(true);
});

3. 临时修复:同步真实DOM与Enzyme(不推荐长期使用)

如果暂时无法修改组件逻辑,可在测试中模拟真实DOM环境,并直接检查真实DOM的状态:

it("should hide the continue button if it exists", () => {
  // 先在真实DOM中添加目标按钮
  const continueBtn = document.createElement('button');
  continueBtn.className = 'continue-button';
  document.body.appendChild(continueBtn);

  // 重新挂载组件触发componentDidMount
  wrapper = mount(<FraudStatement/>);

  // 直接检查真实DOM中的按钮样式
  expect(document.querySelector('.continue-button').classList.contains('hidden')).toBe(true);

  // 测试后清理DOM
  document.body.removeChild(continueBtn);
});

4. 额外优化:隔离测试依赖

测试时需要Mock外部依赖,避免无关逻辑干扰:

beforeEach(() => {
  // Mock props中的回调函数
  const mockUpdateApplicableCoverages = jest.fn();
  // 明确传入props,避免默认值触发跳转逻辑
  wrapper = mount(
    <FraudStatement 
      isSubmissionComplete={false}
      updateApplicableCoverages={mockUpdateApplicableCoverages}
    />
  );
});

内容的提问来源于stack exchange,提问作者Tapesh Patel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 21:17:12