单元测试具有依赖关系的AngularJS工厂

时间:2013-05-15 12:53:20

标签: angularjs jasmine karma-runner

在对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();

    }
  ]);
})

N.B。我知道$controller允许这个用于控制器,但我没有看到工厂的等价物。

2 个答案:

答案 0 :(得分:91)

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

  1. 使用$provide和匿名模块注入模拟。
  2. 注入您想要模拟的服务,并使用jasmine的间谍功能来提供模拟值。
  3. 第二个选项仅在您确切知道被测代码将在注入的服务上调用哪些方法并且您可以轻松地模拟它们时才有效。由于您似乎正在访问服务上的数据属性(而不是方法),因此追求第一个选项可能是最好的。

    使用$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 :(得分:12)

@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()允许您引入依赖关系,就像您在正常的角度应用程序中所期望的那样 - 因此您可以建立需求来支持测试依赖的东西在他们身上。