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

如何测试依赖document全局对象的函数?单元测试入门咨询

如何测试依赖document全局对象的函数?

嘿,你要测试的是那个适配浏览器前缀的过渡/动画结束事件函数对吧?这类依赖document全局对象的函数其实没那么难搞,我给你分享几个实用的方案,结合你的场景具体来说:

1. 用测试框架自带的浏览器环境模拟(以Jest为例)

像Jest这类现代测试框架自带了jsdom,能帮你模拟出浏览器里的document对象。你只需要在测试前手动修改document.body.style,就能模拟不同浏览器的属性支持情况,覆盖所有分支。

测试代码示例:

const animEndString = require('./你的函数文件路径.js');

describe('animEndString 函数测试', () => {
  // 每个测试前重置style属性,避免测试间互相影响
  beforeEach(() => {
    // 清空过渡相关属性
    delete document.body.style.OTransition;
    delete document.body.style.WebkitTransition;
    delete document.body.style.MozTransition;
    delete document.body.style.transition;
    // 清空动画相关属性
    delete document.body.style.OAnimation;
    delete document.body.style.WebkitAnimation;
    delete document.body.style.MozAnimation;
    delete document.body.style.animation;
  });

  test('标准浏览器下返回transitionend', () => {
    // 模拟支持标准transition属性
    document.body.style.transition = '';
    expect(animEndString('transition')).toBe('transitionend');
  });

  test('WebKit内核浏览器返回webkitTransitionEnd', () => {
    document.body.style.WebkitTransition = '';
    expect(animEndString('transition')).toBe('webkitTransitionEnd');
  });

  test('旧版Opera浏览器返回oTransitionEnd', () => {
    document.body.style.OTransition = '';
    expect(animEndString('transition')).toBe('oTransitionEnd');
  });

  // 动画类型的测试同理
  test('WebKit内核下动画返回webkitAnimationEnd', () => {
    document.body.style.WebkitAnimation = '';
    expect(animEndString('animation')).toBe('webkitAnimationEnd');
  });
});

2. 抽离依赖,让函数更“好测”

另一种思路是把依赖document的部分抽成可选参数,让函数逻辑和浏览器环境解耦。这样测试的时候完全不需要碰真实或模拟的document,直接传个模拟对象就行。

修改后的函数代码:

const animEndString = (type = 'transition', styleEl = document.body.style) => {
  const types = type === 'transition' 
    ? {
        OTransition: 'oTransitionEnd',
        WebkitTransition: 'webkitTransitionEnd',
        MozTransition: 'transitionend',
        transition: 'transitionend'
      }
    : {
        OAnimation: 'oAnimationEnd',
        WebkitAnimation: 'webkitAnimationEnd',
        MozAnimation: 'animationend',
        animation: 'animationend'
      };

  // 遍历找到第一个存在的属性对应的事件名
  for (const prop in types) {
    if (prop in styleEl) {
      return types[prop];
    }
  }
  // 兜底返回标准事件名
  return type === 'transition' ? 'transitionend' : 'animationend';
};

对应的测试代码:

const animEndString = require('./你的函数文件路径.js');

describe('animEndString 函数测试', () => {
  test('标准过渡支持返回transitionend', () => {
    const mockStyle = { transition: '' };
    expect(animEndString('transition', mockStyle)).toBe('transitionend');
  });

  test('WebKit过渡支持返回webkitTransitionEnd', () => {
    const mockStyle = { WebkitTransition: '' };
    expect(animEndString('transition', mockStyle)).toBe('webkitTransitionEnd');
  });

  test('标准动画支持返回animationend', () => {
    const mockStyle = { animation: '' };
    expect(animEndString('animation', mockStyle)).toBe('animationend');
  });
});

这种方式不仅让测试更简单,还让函数的复用性更强——比如以后想在非浏览器环境(比如Node.js里做一些样式检测)用它,直接传个自定义对象就行。

3. 手动引入jsdom模拟环境(适合Mocha等框架)

如果你的项目用的是Mocha这类没有内置jsdom的测试框架,那就手动装个jsdom来模拟浏览器环境:

先安装依赖:

npm install jsdom --save-dev

然后在测试文件顶部配置:

const { JSDOM } = require('jsdom');
const dom = new JSDOM('<!DOCTYPE html><body></body>');
// 把模拟的document和window挂到全局
global.document = dom.window.document;
global.window = dom.window;

const animEndString = require('./你的函数文件路径.js');

// 后续测试逻辑就和第一种方案一样啦

总结一下:如果想快速搞定,用Jest自带的环境模拟最省心;如果想让代码更健壮灵活,抽离依赖是最优解;要是用的是旧框架,手动引jsdom也能解决问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 11:45:03