Unit-Test AngularJS-Fabriken mit Abhängigkeiten

78

Wie füge ich beim Testen einer Angular-Fabrik (mit Karma + Jasmine) eine Stub-Abhängigkeit in die zu testende Fabrik ein?

Hier ist meine Fabrik:

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

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

oneOfMyOtherServices wird benötigt, wenn meine Fabrik instanziiert wird.

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

    }
  ]);
})

NB Ich weiß, $controllerdass dies für Controller möglich ist, aber ich sehe kein Äquivalent für Fabriken.

Roy Truelove
quelle

Antworten:

92

Es gibt zwei Möglichkeiten, um so etwas zu erreichen, von denen ich weiß:

  1. Verwenden Sie $provideund ein anonymes Modul, um den Mock zu injizieren.
  2. Injizieren Sie den Dienst, den Sie verspotten möchten, und nutzen Sie die Spionagefähigkeit von Jasmin, um Scheinwerte bereitzustellen.

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

Die Verwendung $providewü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();
  }));
});
Noah Freitas
quelle
Ja, ich denke, Wahl 1 ist der richtige Weg. Vielen Dank!
Roy Truelove
7
Ich möchte die myFactory in alle Tests einbinden. Kann es in einem vor jedem gemacht werden? Ich habe es versucht, aber es hat nicht funktioniert ...
Bennett McElwee
10
Danke für diese Antwort +1. Der Vollständigkeit halber wäre es schön, ein Codebeispiel auch für Option 2 hinzuzufügen.
Klode
2
@ BennettMcElwee Ja, das kannst du. So: var theFactory; beforeEach(inject(function(myFactory) { theFactory = myFactory; } )));Dann theFactoryin Ihrem Test verwenden.
Bentsai
1
Wie kann ich diese Factory-Methode getItemList mit Jasmine und Karma testen? Ich erhalte die Fehlermeldung: [$ injizierer: unpr] fehler.angularjs (function () {angle.module ('riskCanvasApp'). Factory ('itemsService', itemsService); itemsService. $ Inject = ['$ http', '$ q ',' $ compile ',' UrlService ',' accountDetailsMainService ',' sharedService ',' authenticationSvc ']; Funktion itemsService ($ http, $ q, $ compile, urlService, accountDetailsMainService, sharedService, authenticationSvc) {
AMRESH PANDEY
12

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

Hier ist ein Test, jasmineder ungefähr das tut, wonach Sie suchen. Hinweis: Dies erfordert die angular-mocksAufnahme (dies bietet Funktionen wie moduleund 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 ein Beispiel dafür, 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 einzuziehen, wie Sie es in Ihrer normalen Winkelanwendung erwarten würden - und als solche Anforderungen aufzubauen, um das Testen von Dingen zu unterstützen, die auf ihnen beruhen.

AJ.
quelle
2
Sie haben den Teil verpasst, in dem Sie MyFactory beim Testen eine Stub-Abhängigkeit zuweisen.
Skolsuper
Wo ist die zweite Abhängigkeit?
Choco