【问题标题】:Unit testing AngularJS factories that have dependencies对具有依赖项的 AngularJS 工厂进行单元测试
【发布时间】:2013-05-10 01:16:56
【问题描述】:

在对 Angular 工厂(使用 Karma + Jasmine)进行单元测试时,如何将存根依赖项注入被测工厂?

这是我的工厂:

mod = angular.module('myFactoryMod', []);

mod.factory('myFactory', [
  '$log', 'oneOfMyOtherServices', function($log, svc) {
    return makeSomethingThatDoesSomethingWithTheseDependencies($log, svc);
  }
]);

实例化我的工厂时需要oneOfMyOtherServices

这是我的测试:

it('can get an instance of my factory', function() {
  var oneOfMyOtherServicesStub;

  angular.mock.module('myFactoryMod');

  oneOfMyOtherServicesStub = {
    someVariable: 1
  };

  //****How do I get my stub in my target? ****

  angular.mock.inject(['myFactory', function(target) {

      expect(target).toBeDefined();

    }
  ]);
})

注意我知道$controller 允许控制器这样做,但我看不到工厂的等效项。

【问题讨论】:

    标签: angularjs jasmine karma-runner


    【解决方案1】:

    据我所知,有两种方法可以完成这样的事情:

    1. 使用$provide 和匿名模块注入模拟。
    2. 注入您要模拟的服务,并使用 jasmine 的间谍功能提供模拟值。

    第二个选项只有在您确切地知道您的测试代码将在注入的服务上调用哪些方法并且您可以轻松地模拟它们时才有效。由于您似乎正在访问服务上的数据属性(而不是方法),因此选择第一个选项可能是最好的。

    使用$provide 大致如下所示:

    describe('myFactory', function () {
      // Load your module.
      beforeEach(module('myFactoryMod'));
    
      // Setup the mock service in an anonymous module.
      beforeEach(module(function ($provide) {
        $provide.value('oneOfMyOtherServicesStub', {
            someVariable: 1
        });
      }));
    
      it('can get an instance of my factory', inject(function(myFactory) {
        expect(myFactory).toBeDefined();
      }));
    });
    

    【讨论】:

    • 是的,我认为选择 1 是要走的路。谢谢!
    • 我想将 myFactory 注入到所有测试中。可以在 beforeEach 中完成吗?我试过了,但没用……
    • 感谢您的回答 +1。为了完整起见,最好为选项 #2 添加一个代码示例。
    • @BennettMcElwee 是的,你可以。像这样:var theFactory; beforeEach(inject(function(myFactory) { theFactory = myFactory; } ))); 然后在你的测试中使用theFactory
    • 如何使用 Jasmine 和 karma 测试这个工厂方法 getItemList。我收到错误消息: [$injector:unpr] errors.angularjs (function() { angular.module('riskCanvasApp').factory('itemsService', itemsService); itemsService.$inject = [ '$http', '$ q','$compile', 'UrlService', 'accountDetailsMainService', 'sharedService', 'authenticationSvc' ]; function itemsService($http, $q, $compile, urlService, accountDetailsMainService, sharedService, authenticationSvc) {
    【解决方案2】:

    @bentsai 的评论其实对测试服务很有帮助;为了完整起见,我添加了一个示例。

    这是对jasmine 的测试,它与您正在寻找的内容大致相同。注意:这要求您包含angular-mocks(这是提供moduleinject 之类的功能)。

    describe('app: myApp', function() {
      beforeEach(module('myApp'));
      var $controller;
      beforeEach(inject(function(_$controller_) {
        $controller = _$controller_;
      }));
      // Factory of interest is called MyFactory
      describe('factory: MyFactory', function() {
        var factory = null;
        beforeEach(inject(function(MyFactory) {
          factory = MyFactory;
        }))
        it('Should define methods', function() {
          expect(factory.beAwesome).toBeDefined()
          expect(factory.beAwesome).toEqual(jasmine.any(Function))
        });
      });
    });
    

    这是模块和相关工厂定义的存根:

    var app = angular.module('myApp', []);
    app.factory('MyFactory', function() {
      var factory = {};
      factory.beAwesome = function() {
        return 'Awesome!';
      }
      return factory;
    });
    

    在这种情况下,很明显inject() 的使用允许您引入依赖项,就像您在正常的 Angular 应用程序中所期望的一样 - 因此您可以构建需求以支持测试依赖它们的事物.

    【讨论】:

    • 您错过了在测试中向 MyFactory 注入存根依赖项的部分。
    • 第二个依赖在哪里?
    猜你喜欢
    • 2017-09-03
    • 1970-01-01
    • 1970-01-01
    • 2015-10-18
    • 1970-01-01
    • 1970-01-01
    • 2010-12-25
    • 2014-05-29
    • 1970-01-01
    相关资源
    最近更新 更多