如何单元测试/模拟$timeout调用?求spyOn模拟$timeout示例
验证AngularJS中$timeout的调用正确性及spyOn模拟示例
针对你提供的这段submitRequest函数,我们可以通过单元测试来验证$timeout是否被传入了正确的函数调用和延迟时间,下面是完整的测试示例,使用Jasmine的spyOn来模拟$timeout服务:
首先,假设这段代码属于某个AngularJS控制器(比如RequestController),我们先搭建测试的基础结构:
describe('RequestController', function() { var $scope, $timeout, $controller; // 加载你的Angular模块 beforeEach(module('yourAppModuleName')); // 注入所需服务并初始化控制器 beforeEach(inject(function(_$rootScope_, _$timeout_, _$controller_) { $scope = _$rootScope_.$new(); $timeout = _$timeout_; $controller = _$controller_; // 初始化控制器,传入$scope和$timeout $controller('RequestController', { $scope: $scope, $timeout: $timeout }); // 用spyOn模拟$timeout服务,保留其原有行为(可选,若不需要真实执行可改用and.stub()) spyOn($timeout).and.callThrough(); })); it('should invoke $timeout with correct function and 2000ms delay', function() { // 第一步:模拟依赖的getData函数,避免真实调用 // 注意:如果getData是$scope的方法,改为spyOn($scope, 'getData') spyOn(window, 'getData').and.returnValue(JSON.stringify({ test: 'data' })); // 第二步:调用要测试的submitRequest方法 $scope.submitRequest(); // 验证$timeout是否被调用过 expect($timeout).toHaveBeenCalled(); // 获取$timeout的调用参数,检查延迟时间是否为2000ms var timeoutArgs = $timeout.calls.mostRecent().args; expect(timeoutArgs[1]).toBe(2000); // 第三步:验证$timeout传入的函数逻辑是否正确(即触发submitForm的click事件) // 模拟jQuery的click方法 spyOn($('#submitForm'), 'click'); // 执行$timeout中传入的函数 timeoutArgs[0](); // 验证click事件是否被触发 expect($('#submitForm').click).toHaveBeenCalled(); }); });
关键说明:
- spyOn的使用:因为
$timeout是AngularJS内置的服务函数,直接spyOn($timeout)即可监听它的调用;如果需要保留$timeout的原有执行逻辑,加上.and.callThrough(),如果只想模拟调用不执行内部逻辑,改用.and.stub()。 - 处理依赖:测试中必须模拟
getData函数,否则会因为找不到该函数而报错,根据getData的实际定义位置调整spy的目标(全局方法或$scope方法)。 - 避免真实延迟:在单元测试中,不要等待2000ms,而是可以调用
$timeout.flush()来立即执行所有pending的超时任务,这样测试会更高效(在调用$scope.submitRequest()后添加$timeout.flush()即可)。 - 验证函数逻辑:通过取出
$timeout调用时传入的函数并手动执行,我们可以验证这个函数是否正确触发了$('#submitForm').click()。
内容的提问来源于stack exchange,提问作者GC_
相关产品推荐
相关产品推荐

