javascript - Jasmine 测试不会进入 promise 的 then 部分

标签 javascript angularjs unit-testing jasmine

我想测试这个功能:

    function initializeView() {
        var deferred = $q.defer();
        if(this.momentArray) {
            core.listMoments(constants.BEST_MOMENT_PREFIX, '').then(function(moments) {
                //Ommitted
                deferred.resolve(moments);      
            }, function(error) {
                console.log("ERROR");
                deferred.reject(error);
            });
        }
        else {
            deferred.resolve();
        }
        return deferred.promise;    
    };

函数调用core.listMoments:

    function listMoments(prefix, startAfter) {
        // var deferred = $q.defer();
        var promises = [];
        return awsServices.getMoments(prefix, startAfter).then(function(moments) { //Mocked
            console.log("getMoments Returned"); //Does not print
            for(var i = 0; i < moments.length; i++) {
                // moments[i].Key = constants.IMAGE_URL + moments[i].Key;
                promises.push(getMomentMetaData(moments[i]));
            }
        return $q.all(promises);
        });
    };

这是我的测试函数:

it('Should correctly initialize the view', function(done) {
    spyOn(awsServices, 'getMoments').and.callFake(function() {
        console.log("getMoments Has been mocked"); //This prints
        return $q.resolve(mock_moment);
    });
    service.initializeView().then(function() {
        done();
    })
});

问题出在 awsServices 的“getMoments”模拟上。对 awsServices.getMoments 的调用在 listMoments 函数中。我想模拟这个函数,但是当我这样做时它不会执行 promise 的“then”部分。

因此,根据我的控制台日志,它会打印“getMoments Has been mocked”日志,但不会打印“getMoments Returned”日志。所以这个函数被模拟了,但由于某种原因它没有进入 then 语句,我的测试只是超时了。

最佳答案

为了让 promise 的 .then() 部分在这样的测试中工作,您需要使用 $rootScope.$apply()。无论 promise 是在您的测试代码中还是在被测试的引用库中,这都是必需的。可以把它想象成 $http$timeout 调用的 flush() 函数。

Angular documentation's $q page 中的测试示例显示如何使用它:

it('should simulate promise', inject(function($q, $rootScope) {
  var deferred = $q.defer();
  var promise = deferred.promise;
  var resolvedValue;

  promise.then(function(value) { resolvedValue = value; });
  expect(resolvedValue).toBeUndefined();

  // Simulate resolving of promise
  deferred.resolve(123);
  // Note that the 'then' function does not get called synchronously.
  // This is because we want the promise API to always be async, whether or not
  // it got called synchronously or asynchronously.
  expect(resolvedValue).toBeUndefined();

  // Propagate promise resolution to 'then' functions using $apply().
  $rootScope.$apply();
  expect(resolvedValue).toEqual(123);
}));

请注意,它们注入(inject)了 $rootScope

关于javascript - Jasmine 测试不会进入 promise 的 then 部分,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46029880/

相关文章:

javascript - $.post() 的第三个参数不起作用

javascript - Angular 图表未显示在我的页面中

javascript - 收集数字并将其转换为 AngularJS 中的日期

angularjs - 如何使用 grunt 丑化一个有 Angular 的项目?

android - Android 中的单元测试私有(private)函数

javascript - 在javascript中将时间戳转换为特定的日期格式

javascript - onClick 函数需要两次单击才能更新状态

javascript - 在 ASP.NET 中管理 AngularJS 网络应用程序(替代 RequireJS)

c# - 如何使用 EF6、MVC 和 MOQ 有效地模拟数据上下文以进行单元测试

angularjs - 如何使用 Jasmine 在 Angular JS 工厂中测试变量