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

如何为NextJS/React应用中的GTM追踪编写单元测试?

测试GTM追踪函数的单元测试方案

1. 测试前的环境准备

测试环境(如Jest)默认不存在浏览器的window.dataLayer,需要提前模拟:

// 在测试文件顶部或jest.setup.js中初始化
global.window.dataLayer = [];

2. 测试追踪函数的Payload构建

假设你的核心追踪函数如下:

// tracking.js
export const trackAddToCart = (productData, userData) => {
  const eventData = {
    event: 'addToCart',
    ecommerce: {
      items: [{
        item_id: productData.id,
        item_name: productData.name,
        price: productData.price,
        quantity: 1
      }],
      user_id: userData.id,
      user_type: userData.type
    }
  };
  window.dataLayer.push(eventData);
};

对应测试用例,验证Payload结构和数据正确性:

// tracking.test.js
import { trackAddToCart } from './tracking';

describe('trackAddToCart', () => {
  beforeEach(() => {
    // 每次测试前清空dataLayer,避免用例污染
    global.window.dataLayer = [];
  });

  it('生成符合要求的事件Payload', () => {
    const mockProduct = { id: 'prod_123', name: '测试商品', price: 99.99 };
    const mockUser = { id: 'user_456', type: '注册用户' };

    trackAddToCart(mockProduct, mockUser);
    
    const pushedEvent = window.dataLayer.at(-1);
    expect(pushedEvent.event).toBe('addToCart');
    expect(pushedEvent.ecommerce.items[0]).toEqual({
      item_id: 'prod_123',
      item_name: '测试商品',
      price: 99.99,
      quantity: 1
    });
    expect(pushedEvent.ecommerce.user_id).toBe('user_456');
    expect(pushedEvent.ecommerce.user_type).toBe('注册用户');
  });
});

3. 验证window.dataLayer.push的调用行为

用Jest的spy监听push方法,确认调用次数和参数:

it('正确调用window.dataLayer.push', () => {
  const mockProduct = { id: 'prod_123', name: '测试商品', price: 99.99 };
  const mockUser = { id: 'user_456', type: '注册用户' };
  
  // 创建spy并替换原方法
  const pushSpy = jest.spyOn(window.dataLayer, 'push').mockImplementation(() => {});

  trackAddToCart(mockProduct, mockUser);

  // 校验调用次数和参数
  expect(pushSpy).toHaveBeenCalledTimes(1);
  expect(pushSpy).toHaveBeenCalledWith(expect.objectContaining({
    event: 'addToCart',
    ecommerce: expect.objectContaining({ user_id: 'user_456' })
  }));

  // 恢复原方法
  pushSpy.mockRestore();
});

4. 组件层面的触发测试

如果追踪函数在React组件中通过用户行为触发(如点击按钮),可以这样测试:

// ProductPage.js
import { trackAddToCart } from './tracking';

const ProductPage = ({ product, user }) => {
  const handleAddToCart = () => {
    trackAddToCart(product, user);
  };

  return <button onClick={handleAddToCart}>加入购物车</button>;
};

export default ProductPage;

对应组件测试用例:

// ProductPage.test.js
import { render, screen, fireEvent } from '@testing-library/react';
import ProductPage from './ProductPage';
import { trackAddToCart } from './tracking';

// 模拟追踪函数
jest.mock('./tracking', () => ({
  trackAddToCart: jest.fn()
}));

describe('ProductPage', () => {
  const mockProduct = { id: 'prod_123', name: '测试商品', price: 99.99 };
  const mockUser = { id: 'user_456', type: '注册用户' };

  it('点击加入购物车按钮触发追踪事件', () => {
    render(<ProductPage product={mockProduct} user={mockUser} />);
    
    const addBtn = screen.getByText('加入购物车');
    fireEvent.click(addBtn);

    expect(trackAddToCart).toHaveBeenCalledTimes(1);
    expect(trackAddToCart).toHaveBeenCalledWith(mockProduct, mockUser);
  });
});

5. 额外注意事项

  • 若使用Next.js App Router,确保追踪函数仅在Client Components中调用(Server Components无window对象),测试时需区分环境。
  • 复杂Payload可使用expect.objectContaining做部分匹配,提升测试灵活性。
  • 所有测试用例执行前,务必重置dataLayer或spy,避免跨用例污染。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 11:35:39