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

需Jasmine测试帮助:如何为嵌套each循环的jQuery逻辑编写测试

如何为嵌套jQuery $.each循环编写Jasmine测试并使用afterEach?

我来帮你一步步搞定这个测试的写法,顺便讲清楚afterEach的用法。首先先把你的代码补全(看起来你没写完判断逻辑,我先按常见的过滤场景补全),然后再写测试用例。

你的原始代码(补全后):

HTML结构

<div id="mj"> 
  <div class="commonclass"> Item 1 </div> 
  <div class="commonclass"> Item 2 </div> 
  <div class="commonclass"> Item 3 </div> 
</div>

jQuery逻辑(补全过滤逻辑)

var filterArray = ['Item', 'Block', 'Item 3']; 
$.each($('.commonclass'), function(i, v) { 
  var matching = false; 
  $.each(filterArray, function(j, w) { 
    // 判断元素文本是否包含filter项
    if ($(v).text().trim().includes(w)) {
      matching = true;
      return false; // 找到匹配就跳出内层循环,提升效率
    }
  });
  // 根据匹配结果控制元素显示/隐藏
  matching ? $(v).show() : $(v).hide();
});

第一步:把业务逻辑封装成函数

为了方便测试,最好把这段过滤逻辑封装成一个可调用的函数,而不是直接写在全局作用域里:

function filterItems(filterArray) {
  $.each($('.commonclass'), function(i, v) { 
    var matching = false; 
    $.each(filterArray, function(j, w) { 
      if ($(v).text().trim().includes(w)) {
        matching = true;
        return false;
      }
    });
    matching ? $(v).show() : $(v).hide();
  });
}

第二步:编写Jasmine测试用例

核心思路

  • 用beforeEach在每个测试前挂载干净的DOM结构
  • 用afterEach在每个测试后清理DOM,避免污染后续测试
  • 针对不同的过滤条件,验证元素的显示/隐藏状态是否符合预期
  • 可以用Jasmine的spy来验证循环的执行次数,确保逻辑覆盖完整

完整测试代码

describe('嵌套$.each的元素过滤逻辑', function() {
  // 每个测试前准备DOM环境和函数引用
  beforeEach(function() {
    // 把测试用的HTML插入到页面中
    $('body').append(`
      <div id="mj"> 
        <div class="commonclass"> Item 1 </div> 
        <div class="commonclass"> Item 2 </div> 
        <div class="commonclass"> Item 3 </div> 
      </div>
    `);
    // 把过滤函数绑定到this上,方便在测试用例中调用
    this.filterItems = filterItems;
  });

  // 每个测试结束后清理DOM
  afterEach(function() {
    // 移除我们挂载的测试DOM,保证下一个测试的环境是干净的
    $('#mj').remove();
  });

  // 测试过滤逻辑的正确性
  it('应该正确显示匹配过滤条件的元素,隐藏不匹配的', function() {
    // 测试场景1:过滤包含"Item"或"Block"的元素
    this.filterItems(['Item', 'Block']);
    expect($('.commonclass:eq(0)').is(':visible')).toBe(true); // Item1包含Item
    expect($('.commonclass:eq(1)').is(':visible')).toBe(true); // Item2包含Item
    expect($('.commonclass:eq(2)').is(':visible')).toBe(true); // Item3包含Item

    // 测试场景2:只过滤"Block",所有元素都不匹配
    this.filterItems(['Block']);
    expect($('.commonclass:eq(0)').is(':visible')).toBe(false);
    expect($('.commonclass:eq(1)').is(':visible')).toBe(false);
    expect($('.commonclass:eq(2)').is(':visible')).toBe(false);

    // 测试场景3:精确匹配"Item 3"
    this.filterItems(['Item 3']);
    expect($('.commonclass:eq(0)').is(':visible')).toBe(false);
    expect($('.commonclass:eq(1)').is(':visible')).toBe(false);
    expect($('.commonclass:eq(2)').is(':visible')).toBe(true);
  });

  // 测试循环的执行情况,确保逻辑覆盖完整
  it('应该遍历所有外层元素,找到匹配后跳出内层循环', function() {
    // 监听$.each方法,同时保留原函数功能
    spyOn($, 'each').and.callThrough();

    this.filterItems(['Item', 'Block']);

    // 外层$.each调用1次(处理3个.commonclass元素)
    // 内层每个元素找到匹配后就跳出,所以内层调用3次(每个元素各1次)
    // 总调用次数是1 + 3 = 4次
    expect($.each.calls.count()).toBe(4);
  });
});

关于afterEach的说明

这里的afterEach函数会在每个测试用例执行完毕后自动运行,它的作用是清理我们在beforeEach中挂载的DOM元素。如果没有这一步,前一个测试留下的#mj元素会留在页面里,可能导致下一个测试的DOM环境混乱,比如重复选择元素、状态污染等问题。简单来说,它就是用来保证每个测试用例都在独立、干净的环境中运行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 08:00:01