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

如何用sinon.js、mocha、chai为含fromEvent(scroll)的addScroll方法编写单元测试

addScroll 方法单元测试实现

核心测试覆盖点

测试需要验证三个核心逻辑,避免漏测:

  • 调用addScroll后,是否正确在$size对象上注册scroll事件监听
  • scroll事件触发时,是否根据pageYOffset是否大于5,正确更新实例的scroll布尔属性
  • 终止信号unSubs$触发后,是否正确取消订阅,不再响应后续scroll事件

测试代码实现

基于mocha运行器、chai断言库、sinon mock工具的测试代码如下,测试前不需要额外引入jsdom等DOM仿真库,直接mock依赖即可:

const { expect } = require('chai');
const sinon = require('sinon');
const { Subject } = require('rxjs');
// 替换为你项目中待测试类的实际引入路径
const ScrollComponent = require('./your-component-path');

describe('addScroll 方法', () => {
  let testComponent;
  let mockScrollContainer;
  let fireScrollEvent;

  beforeEach(() => {
    // 构造mock滚动容器,实现fromEvent依赖的事件注册接口
    mockScrollContainer = {
      pageYOffset: 0,
      addEventListener: sinon.spy(),
      removeEventListener: sinon.spy()
    };
    // 捕获scroll事件回调,方便测试时手动触发
    fireScrollEvent = null;
    mockScrollContainer.addEventListener.callsFake((eventName, handler) => {
      if (eventName === 'scroll') fireScrollEvent = handler;
    });

    // 初始化待测试组件实例,注入mock依赖
    testComponent = new ScrollComponent();
    testComponent.$size = mockScrollContainer;
    testComponent.unSubs$ = new Subject();
    testComponent.scroll = false;
  });

  afterEach(() => {
    // 每个用例执行完触发终止信号,清理订阅,避免测试污染
    testComponent.unSubs$.next();
    testComponent.unSubs$.complete();
    sinon.restore();
  });

  it('调用方法后会成功注册scroll事件监听', () => {
    testComponent.addScroll();
    expect(mockScrollContainer.addEventListener.calledOnceWith('scroll')).to.be.true;
  });

  it('触发scroll事件时,会根据pageYOffset值正确更新scroll属性', () => {
    testComponent.addScroll();
    
    // 偏移量小于等于5时,scroll应为false
    mockScrollContainer.pageYOffset = 3;
    fireScrollEvent();
    expect(testComponent.scroll).to.be.false;

    // 偏移量大于5时,scroll应为true
    mockScrollContainer.pageYOffset = 6;
    fireScrollEvent();
    expect(testComponent.scroll).to.be.true;

    // 偏移量回落至5以下时,scroll应同步改回false
    mockScrollContainer.pageYOffset = 0;
    fireScrollEvent();
    expect(testComponent.scroll).to.be.false;
  });

  it('unSubs$终止信号触发后,不再响应后续scroll事件', () => {
    testComponent.addScroll();
    // 手动触发终止订阅信号
    testComponent.unSubs$.next();
    
    // 触发scroll事件,设置偏移量为满足条件的值
    mockScrollContainer.pageYOffset = 10;
    fireScrollEvent();
    // scroll属性应保持初始值,不会被更新
    expect(testComponent.scroll).to.be.false;
    // 验证事件监听已被移除
    expect(mockScrollContainer.removeEventListener.calledWith('scroll')).to.be.true;
  });
});

适配提示:如果你使用的RxJS版本中fromEvent优先通过on/off方法注册事件,只需要把mock对象里的addEventListener/removeEventListener替换为on/off即可,其他逻辑无需调整。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 21:03:19