web-dev-qa-db-fra.com

Tests unitaires des usines AngularJS ayant des dépendances

Lorsque l’unité teste une Angular factory (avec Karma + Jasmine), comment puis-je injecter une dépendance de stub dans l’usine testée?

Voici mon usine:

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

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

oneOfMyOtherServices est nécessaire pour instancier mon usine.

Voici mon test:

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. Je le sais $controller permet cela pour les contrôleurs, mais je ne vois pas d'équivalent pour les usines.

76
Roy Truelove

À ma connaissance, il existe deux manières d'accomplir quelque chose comme cela:

  1. Utilisation $provide et un module anonyme pour injecter la maquette.
  2. Injectez le service que vous souhaitez simuler et utilisez la capacité d'espionnage de jasmine pour fournir des valeurs factices.

La deuxième option ne fonctionne que si vous savez exactement quelles méthodes votre code testé va appeler sur le service injecté et vous pouvez facilement les imiter. Comme vous semblez accéder à une propriété de données sur le service (plutôt qu’à une méthode), il peut être préférable de choisir la première option.

En utilisant $provide ressemblerait à peu près à ceci:

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

Le commentaire de @bentsai est en réalité très utile pour tester les services; pour compléter, j'ajoute un exemple.

Voici un test pour jasmine qui fait approximativement ce que vous recherchez. Note: cela nécessite que vous ayez angular-mocks Inclus (c'est ce qui fournit des fonctions comme module et 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))
    });
  });
});

Voici un extrait pour ce que le module et la définition de fabrique associée pourraient ressembler:

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

Dans ce cas, il est clair que l'utilisation de inject() vous permet d'extraire des dépendances, comme vous le souhaiteriez dans votre application angular normale - et ainsi, vous pouvez construire en place des exigences pour prendre en charge le test des choses qui en dépendent.

12
AJ.