茉莉花测试没有进入承诺的 then 部分

Mat*_*aNg 3 javascript unit-testing jasmine angularjs

我想测试这个功能:

    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;    
    };
Run Code Online (Sandbox Code Playgroud)

该函数调用 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);
        });
    };
Run Code Online (Sandbox Code Playgroud)

这是我的测试功能:

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();
    })
});
Run Code Online (Sandbox Code Playgroud)

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

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

小智 5

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

Angular 文档的 $q 页面中的测试示例展示了如何使用它:

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);
}));
Run Code Online (Sandbox Code Playgroud)

请注意,它们注入$rootScope.