it-swarm.com.de

Unit Testing von AngularJS-Fabriken mit Abhängigkeiten

Wie kann ich beim Testen einer Angular Factory (mit Karma + Jasmine)) eine Stub-Abhängigkeit in die zu testende Factory einspeisen?

Hier ist meine fabrik:

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

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

oneOfMyOtherServices wird benötigt, um meine Factory zu instanziieren.

Hier ist mein 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. Ich weiß das $controller erlaubt dies für Controller, aber ich sehe kein Äquivalent für Fabriken.

76
Roy Truelove

Es gibt zwei Möglichkeiten, um so etwas zu erreichen, die ich kenne:

  1. Verwenden $provide und ein anonymes Modul, um das Mock zu injizieren.
  2. Injizieren Sie den Service, den Sie verspotten möchten, und verwenden Sie die Spionage-Fähigkeit von Jasmine, um verspottete Werte bereitzustellen.

Die zweite Option funktioniert nur, wenn Sie genau wissen, welche Methoden Ihr zu testender Code auf den injizierten Dienst aufruft, und Sie können sie leicht verspotten. Da Sie auf eine Dateneigenschaft des Dienstes (und nicht auf eine Methode) zuzugreifen scheinen, ist es möglicherweise am besten, die erste Option zu verwenden.

Mit $provide würde ungefähr so ​​aussehen:

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

Der Kommentar von @bentsai ist eigentlich sehr hilfreich für das Testen von Diensten; Der Vollständigkeit halber füge ich ein Beispiel hinzu.

Hier ist ein Test für jasmine, der ungefähr das macht, wonach Sie suchen. Hinweis: Hierfür muss angular-mocks Angegeben werden (dies bietet Funktionen wie module und 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))
    });
  });
});

Dies ist eine Zusammenfassung, wie das Modul und die zugehörige Factory-Definition aussehen könnten:

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

In diesem Fall ist es klar, dass die Verwendung von inject() es Ihnen ermöglicht, Abhängigkeiten einzubeziehen, genau wie Sie es in Ihrer normalen angular Anwendung erwarten würden - und als solche können Sie bauen Anforderungen für das Testen von Dingen, die darauf angewiesen sind.

12
AJ.