AngularJS:需要帮助对具有承诺的工厂进行单元测试

时间:2013-04-05 12:02:20

标签: unit-testing angularjs promise

我有一个使用promise来解析json文件的工厂。 它应该只在第一次解析此文件并在再次调用时返回结果。

这是工厂

app.factory('getServerConfig', function ($q, $http, serverConfig) {

  return function (fileName) {
    var deferred = $q.defer();

    if (serverConfig.loaded) {
      deferred.resolve("alreadyLoaded");
    } else {
      $http.get(fileName).then(function (result) {
        serverConfig.setConfig(result.data);
        deferred.resolve("loaded");
      }, function (result) {
        deferred.reject();
      });
    }
    return deferred.promise;
  };
})

我是如何测试的:

it('should say hallo to the World', inject(function(getServerConfig) {
    var promiseResult;

    getServerConfig("server-config.json").then(function (result) {
      promiseResult = result;
    });

    rootScope.$apply();
    expect(promiseResult).toBe('loaded');
}));

不幸的是,看起来像promiseResult从未设置过。 这是一个代码为http://plnkr.co/edit/uRPCjuUDkqPRAv07G5Nx?p=preview

的plunker

1 个答案:

答案 0 :(得分:3)

问题是$ httpBackend需要flush()(请查看Flushing HTTP requests),这样您就可以在测试中模仿$http异步行为。

要解决此问题,请存储$httpBackend的引用(或再次注入)并在请求完成后调用$ httpBack.flush()。

查找

it('should say hallo to the World', inject(function(getServerConfig, $httpBackend) {
  var promiseResult;

  getServerConfig("server-config.json").then(function (result) {
    promiseResult = result;
  });

  $httpBackend.flush();
  expect(promiseResult).toBe('loaded');
}));

如果您要在大多数规范中使用$httpBackend,请考虑将其存储在本地变量中,并在beforeEach中进行设置。