1

我一直在用 Angular 编写一些 Jasmine 单元测试。在第一个示例中,我正在测试一个控制器。

myApp.controller('MyCtrl', function($scope, Config){
    ...
});

我有一个配置服务 (Config),它保存数据库中的配置并注入到我的控制器中。由于这是一个单元测试,我想完全模拟该配置服务,而不是允许执行通过它并使用 $httpBackend。我发现的示例教会了我一个 $controller 函数,我可以像这样使用它,以便获得我的控制器实例,其中注入了我的模拟来代替通常的协作者:

beforeEach(inject(function($controller, $rootScope){
  var scope = $rootScope.$new();
  var configMock = { 
    theOnlyPropertyMyControllerNeeds: 'value'
  };
  ctrl = $controller('MyCtrl', {
            $scope:scope, 
            Config: configMock
        });
}));

但我还有其他使用 Config 服务的服务。为了帮助对它们进行单元测试,我假设会有一个类似的 $service 函数,我可以使用我想提供的任何模拟来实例化服务。没有。我尝试了 $injector.get,但它似乎并没有让我通过我的模拟。搜索了一段时间后,为了单独实例化服务(避免实例化其协作者),我能想到的最好方法是:

beforeEach(function() {
  mockConfig = { 
    thePropertyMyServiceUses: 'value'
  };

  module(function($provide) {
    $provide.value('Config', mockConfig);
  });

  inject(function($injector) {
    myService = $injector.get('MyService');
  });
});

这是正确的方法吗?它似乎覆盖了整个应用程序对 Config 服务的定义,这似乎有点矫枉过正。

这是唯一的方法吗?为什么没有 $service 辅助方法?

4

1 回答 1

1

对于单元测试,您通常会为了测试而覆盖服务。但是,您可以使用 $provide 覆盖现有服务而不是使用注入,只要您事先加载应用程序即可。

假设您Config使用以下内容创建:

angular.moduel('...', [...]).factory('Config', function (...) {...});

如果是这样,试试这个:

...
beforeEach(module("<Name of you App>"));

beforeEach(
    module(function ($provide) {
        $provide.factory('Config', function (...) {...});
    });
);
...

之后,当你初始化你的控制器时,它会得到 mocked Config

于 2013-05-09T21:30:34.750 回答