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

AngularJS/Jasmine中嵌套Promise的单元测试实现求助

针对嵌套Promise函数的AngularJS/Jasmine单元测试方案

没问题,我来帮你搞定这个嵌套Promise函数的单元测试。咱们先理清楚functionToTest的核心逻辑:它会先检查是否有未保存变更,再根据用户的确认操作,走两条不同的Promise链。接下来我会分步骤展示如何mock依赖、编写测试用例,覆盖所有关键场景。

第一步:准备测试环境与Mock依赖

首先要mock掉函数里的依赖——customService和hasUnsavedChanges函数,同时注入AngularJS测试必备的$q和$rootScope(因为AngularJS的Promise依赖digest循环才能resolve)。

describe('functionToTest', function() {
  var customService;
  var $q;
  var $rootScope;
  // 模拟hasUnsavedChanges检查函数
  var hasUnsavedChanges;

  beforeEach(module('yourAppModuleName')); // 替换成你的实际模块名

  beforeEach(inject(function(_$q_, _$rootScope_) {
    $q = _$q_;
    $rootScope = _$rootScope_;

    // Mock customService的所有用到的方法
    customService = jasmine.createSpyObj('customService', [
      'confirm', 'openSomething', 'doneSomething', 
      'doSomething', 'doSomethingBeforeDone'
    ]);

    // 让每个mock方法默认返回resolved状态的Promise
    customService.confirm.and.returnValue($q.resolve(true));
    customService.openSomething.and.returnValue($q.resolve('mockData'));
    customService.doneSomething.and.returnValue($q.resolve());
    customService.doSomething.and.returnValue($q.resolve());
    customService.doSomethingBeforeDone.and.returnValue($q.resolve());

    // 模拟hasUnsavedChanges函数
    hasUnsavedChanges = jasmine.createSpy('hasUnsavedChanges').and.returnValue(false);
  }));

  // 测试用例会写在这里
});

第二步:编写测试用例,覆盖所有场景

场景1:没有未保存变更,函数直接返回

当hasUnsavedChanges()返回false时,函数不会进入任何Promise逻辑,我们要验证这一点:

it('should do nothing when there are no unsaved changes', function() {
  // 给定:没有未保存变更
  hasUnsavedChanges.and.returnValue(false);

  // 执行函数
  var result = functionToTest();

  // 断言:customService的所有方法都没被调用
  expect(customService.confirm).not.toHaveBeenCalled();
  expect(result).toBeUndefined(); // 函数没有返回Promise,结果为undefined
});

场景2:有未保存变更,用户确认操作

当hasUnsavedChanges()返回true,且用户点击确认(confirm()返回true),要验证流程走openSomething → doneSomething的链:

it('should execute openSomething -> doneSomething when user confirms', function(done) {
  // 给定:有未保存变更,且用户确认
  hasUnsavedChanges.and.returnValue(true);
  customService.confirm.and.returnValue($q.resolve(true));

  // 执行函数
  var promise = functionToTest();

  // 触发digest循环,让Promise resolve
  $rootScope.$apply();

  // 断言Promise执行完成后的逻辑
  promise.then(function() {
    expect(customService.confirm).toHaveBeenCalled();
    expect(customService.openSomething).toHaveBeenCalled();
    expect(customService.doneSomething).toHaveBeenCalled();
    // 验证取消分支的方法完全没被调用
    expect(customService.doSomething).not.toHaveBeenCalled();
    done(); // 通知Jasmine异步测试完成
  }).catch(function(err) {
    done.fail(err); // 如果Promise失败,标记测试失败
  });
});

场景3:有未保存变更,用户取消操作

当hasUnsavedChanges()返回true,但用户取消(confirm()返回false),要验证流程走doSomething → doSomethingBeforeDone的嵌套链:

it('should execute doSomething -> doSomethingBeforeDone when user cancels', function(done) {
  // 给定:有未保存变更,且用户取消
  hasUnsavedChanges.and.returnValue(true);
  customService.confirm.and.returnValue($q.resolve(false));

  // 执行函数
  var promise = functionToTest();

  // 触发digest循环
  $rootScope.$apply();

  promise.then(function() {
    expect(customService.confirm).toHaveBeenCalled();
    expect(customService.doSomething).toHaveBeenCalled();
    expect(customService.doSomethingBeforeDone).toHaveBeenCalled();
    // 验证确认分支的方法完全没被调用
    expect(customService.openSomething).not.toHaveBeenCalled();
    done();
  }).catch(function(err) {
    done.fail(err);
  });
});

关键注意事项

  • 所有涉及Promise的测试都是异步的,必须用done回调通知Jasmine测试完成
  • 一定要调用$rootScope.$apply()触发AngularJS的digest循环,否则Promise永远不会resolve
  • 如果需要测试data参数的处理逻辑,可以给openSomething的mock返回特定数据
  • 如果functionToTest是控制器里的方法,需要先实例化控制器并注入mock服务

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 09:50:08