Модульное тестирование AngularJS фабрик, которые имеют зависимости


при модульном тестировании угловой фабрики (с 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 72

2 ответа:

есть два способа выполнить что-то вроде этого, что я знаю:

  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();
  }));
});

комментарий @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() позволяет вам втягивать зависимости, как и следовало ожидать в вашем обычном угловом приложении, и поэтому вы можете создавать требования для поддержки тестирования вещей, которые полагаются на них.