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


79

Під час модульного тестування фабрики 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це дозволяє для контролерів, але я не бачу еквівалента для заводів.

Відповіді:


93

Я знаю два способи досягти чогось подібного:

  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 - це шлях. Дякую!
Рой Truelove

7
Я хотів би ввести myFactory у всі тести. Чи можна це зробити за допомогою beforeEach? Я спробував, але це не спрацювало ...
Беннетт МакЕлві

10
Дякую за цю відповідь +1. Було б непогано додати приклад коду також для варіанту №2, для повноти.
klode

2
@BennettMcElwee Так, ти можеш. Ось так: var theFactory; beforeEach(inject(function(myFactory) { theFactory = myFactory; } )));Тоді використовуйте theFactoryу своєму тесті.
bentsai

1
Як я можу протестувати цей заводський метод getItemList, використовуючи Жасмин та Карма. Я отримую помилку: [$ injector: unpr] error.angularjs (function () {angular.module ('riskCanvasApp'). Factory ('itemsService', itemsService); itemsService. $ Inject = ['$ http', '$ д », '$ компіляції', 'urlService', 'accountDetailsMainService', 'sharedService', 'authenticationSvc']; функція itemsService ($ HTTP, $ д, $ компілювати, urlService, accountDetailsMainService, sharedService, authenticationSvc) {
AMRESH Пандей

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.