对具有依赖项的AngularJS工厂进行单元测试


78

在对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允许用于控制器,但是我没有看到与之等效的工厂。

Answers:


92

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

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

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

使用$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是要走的路。谢谢!
罗伊·特鲁伊

7
我想将myFactory注入所有测试中。可以在beforeEach中完成吗?我尝试过,但没有成功……
Bennett McElwee

10
感谢您的答案+1。为完整起见,还可以为选项#2添加一个代码示例。
klode 2013年

2
@BennettMcElwee是的,可以。像这样:var theFactory; beforeEach(inject(function(myFactory) { theFactory = myFactory; } )));然后theFactory在您的测试中使用。
bentsai 2014年

1
如何使用Jasmine和karma测试此工厂方法getItemList。我收到错误:[$注射器:unpr] errors.angularjs 。(函数(){angular.module( 'riskCanvasApp')工厂( 'itemsService',itemsService); itemsService $注入= [ '$ HTTP',“$ q','$ compile','UrlService','accountDetailsMainService','sharedService','authenticationSvc'];函数itemsService($ http,$ q,$ compile,urlService,accountDetailsMainService,sharedService,authenticationSvc){
AMRESH PANDEY

12

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

这是一个测试,jasmine可以满足您的需求。注意:这需要您angular-mocks包括在内(这是提供module和等功能的功能inject)。

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


2
您已经错过了在测试中向MyFactory注入存根依赖关系的部分。
skolsuper

第二个依赖在哪里?
Choco
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.