Heim > Web-Frontend > js-Tutorial > Verspottete Abhängigkeiten in AngularJS -Tests

Verspottete Abhängigkeiten in AngularJS -Tests

Jennifer Aniston
Freigeben: 2025-02-20 12:28:16
Original
361 Leute haben es durchsucht

Mocking Dependencies in AngularJS Tests

Kernpunkte

  • AngularJS wird unter Berücksichtigung von Tests geboren, und sein integrierter Abhängigkeitsinjektionsmechanismus ermöglicht es, dass jede Komponente mit einem JavaScript-Test-Framework (wie Jasmine) getestet wird.
  • Mocks in Unit -Tests beinhalten die Fähigkeit, Testcode -Snippets zu isolieren, was eine Herausforderung sein kann, da die Abhängigkeiten aus verschiedenen Quellen stammen. Die Simulation in AngularJs wird mit dem angular-mocks -Modul vereinfacht, das Simulationen für eine Reihe häufig verwendeter AngularJS -Dienste liefert.
  • Servicesimulation in AngularJs kann erreicht werden, indem Instanzen von tatsächlichen Diensten erfasst und Dienste anhören oder $provide zur Implementierung von Simulationsdiensten verwendet werden. Die letztere Methode ist vorzuziehen, wodurch vermeiden kann, dass die tatsächliche Methode implementiert wird.
  • Anbietersimulation in AngularJS folgt ähnliche Regeln wie Servicesimulation. Die Methode $get muss im Test implementiert werden. Wenn die in der $get -Funktion definierte Funktion in der Testdatei nicht erforderlich ist, kann ihnen einer leeren Funktion ein Wert zugeordnet werden.
  • globale Objekte (z. nach Bedarf. $window
AngularJS -Designkonzept beinhaltet Tests. Der Quellcode des Frameworks ist sehr gut getestet und jeder mit dem Framework geschriebene Code ist ebenfalls prüfbar. Der eingebaute Abhängigkeitsinjektionsmechanismus ermöglicht es, jede in AngularJS geschriebene Komponente zu testen. Der Code in AngularJS -Anwendungen kann mit einem vorhandenen JavaScript -Test -Framework einheitlich getestet werden. Das häufigste Framework, das zum Testen von AngularJS -Code verwendet wird, ist Jasmin. Alle Beispielcode -Ausschnitte in diesem Artikel werden mit Jasmine geschrieben. Wenn Sie einen anderen Test -Framework in Ihrem Winkelprojekt verwenden, können Sie die in diesem Artikel besprochenen Ideen dennoch anwenden.

In diesem Artikel geht davon aus, dass Sie bereits Erfahrung in der Einheitstests und dem Testen von AngularJS -Code haben. Sie müssen kein Testxperte sein. Wenn Sie ein grundlegendes Verständnis für Tests haben und einige einfache Testfälle für AngularJS -Anwendungen schreiben können, können Sie diesen Artikel weiter lesen.

Die Rolle der Simulation bei Unit -Tests

Die Aufgabe jeder Einheitstests besteht darin, die Funktionalität eines Code -Stücks isoliert zu testen. Das Isolieren des untersuchten Systems kann manchmal eine Herausforderung sein, da Abhängigkeiten aus verschiedenen Quellen stammen können und wir die Verantwortung des zu simulierten Objekts vollständig verstehen müssen.

In nicht statisch typisierten Sprachen wie JavaScript ist die Simulation schwierig, da es nicht leicht ist, die zu simulierte Struktur des Objekts zu verstehen. Gleichzeitig bietet es auch Flexibilität, dh nur einen Teil des Objekts zu simulieren, das derzeit vom zu testenden System verwendet wird, und den Rest zu ignorieren.

Mock im AngularJS -Test

Da eines der Hauptziele von AngularJS Testbarkeit ist, macht das Kernteam zusätzliche Anstrengungen in dies, um das Test zu erleichtern, und bietet uns eine Reihe von Simulationen im angular-mocks -Modul. Dieses Modul enthält Simulationen um einen Satz von AngularJS -Diensten (z. B. $http, $timeout, $animate usw.), die in jeder AngularJS -Anwendung weit verbreitet sind. Dieses Modul verringert die Zeit, die Entwickler benötigen, um Tests zu schreiben.

Diese Simulationen sind sehr hilfreich beim Schreiben von Tests für echte Geschäftsanwendungen. Gleichzeitig reichen sie nicht aus, um die gesamte Anwendung zu testen. Wir müssen Abhängigkeiten im Framework verspotten, aber nicht verspottet - Abhängigkeiten von Plugins von Drittanbietern, globalen Objekten oder Abhängigkeiten, die in der Anwendung erstellt wurden. In diesem Artikel werden einige Tipps zur Verspottung von AngularJS -Abhängigkeiten eingeführt.

Simulationsdienst

Dienste sind die häufigsten Abhängigkeitstypen in AngularJS -Anwendungen. Wie Sie wahrscheinlich bereits wissen, sind Dienste ein überlasteter Begriff in AngularJs. Es kann sich auf einen Dienst, eine Fabrik, einen Wert, einen Konstanten oder einen Anbieter beziehen. Wir werden den Anbieter im nächsten Abschnitt besprechen. Der Dienst kann auf eine der folgenden Arten simuliert werden:

  • Methoden zur Verwendung von Injektionsblöcken, um Instanzen des tatsächlichen Dienstes zu erhalten und den Service anzuhören.
  • Verwenden Sie $provide, um Simulationsdienste zu implementieren.

Ich mag die erste Methode nicht, da sie zur tatsächlichen Methode implementiert werden kann. Wir werden die zweite Methode verwenden, um den folgenden Dienst zu simulieren:

angular.module('sampleServices', [])
  .service('util', function() {
    this.isNumber = function(num) {
      return !isNaN(num);
    };

    this.isDate = function(date) {
      return (date instanceof Date);
    };
  });
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Der folgende Code -Snippet erstellt eine Simulation des obigen Dienstes:

module(function($provide) {
  $provide.service('util', function() {
    this.isNumber = jasmine.createSpy('isNumber').andCallFake(function(num) {
      // 模拟实现
    });
    this.isDate = jasmine.createSpy('isDate').andCallFake(function(num) {
      // 模拟实现
    });
  });
});

// 获取模拟服务的引用
var mockUtilSvc;

inject(function(util) {
  mockUtilSvc = util;
});
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Obwohl das obige Beispiel Jasmine verwendet, um Spione zu erstellen, können Sie es durch Sinon.js ersetzen, um die äquivalente Funktionalität zu erreichen.

Es ist am besten, alle Simulationen nach dem Laden aller für den Test erforderlichen Module zu erstellen. Andernfalls überschreibt die tatsächliche Implementierung die simulierte Implementierung, wenn ein Dienst in einem geladenen Modul definiert ist.

Konstanten, Fabriken und Werte können separat mit $provide.constant, $provide.factory und $provide.value simuliert werden.

Simulationsanbieter

Der Simulationsanbieter ähnelt dem Simulationsdienst. Alle Regeln, die beim Schreiben von Anbietern befolgt werden müssen, müssen ebenfalls befolgt werden, wenn sie sich verspotten. Betrachten Sie den folgenden Anbieter:

angular.module('mockingProviders',[])
  .provider('sample', function() {
    var registeredVals = [];

    this.register = function(val) {
      registeredVals.push(val);      
    };

    this.$get = function() {
      function getRegisteredVals() {
        return registeredVals;
      }

      return {
        getRegisteredVals: getRegisteredVals
      };
    };
  });
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Der folgende Code -Snippet erstellt eine Simulation für den obigen Anbieter:

module(function($provide) {
  $provide.provider('sample', function() {
    this.register = jasmine.createSpy('register');

    this.$get = function() {
      var getRegisteredVals = jasmine.createSpy('getRegisteredVals');

      return {
        getRegisteredVals: getRegisteredVals
      };
    };
  });
});

// 获取提供程序的引用
var sampleProviderObj;

module(function(sampleProvider) {
  sampleProviderObj = sampleProvider;
});
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Der Unterschied zwischen Verweisen auf den Anbieter und andere Singletons besteht darin, dass der Anbieter derzeit nicht im inject() -Block verfügbar ist, da der Anbieter zu diesem Zeitpunkt in eine Fabrik umgewandelt wird. Wir können den module() -Block verwenden, um ihre Objekte zu erhalten.

Bei der Definition eines Anbieters muss auch die $get -Methode im Test implementiert werden. Wenn Sie die in der Funktion $get in der Testdatei definierte Funktion nicht benötigen, können Sie sie einer leeren Funktion zuweisen.

analoges Modul

Wenn das Modul, das in die Testdatei geladen werden soll, eine Reihe anderer Module erfordert, kann das zugegebene Modul nur geladen werden, es sei denn, alle erforderlichen Module sind geladen. Wenn Sie alle diese Module beladen, wird manchmal Tests gescheitert, da einige tatsächliche Servicemethoden aus dem Test aufgerufen werden können. Um diese Schwierigkeiten zu vermeiden, können wir virtuelle Module erstellen, um die gemessenen Module zu laden.

Angenommen, der folgende Code repräsentiert beispielsweise ein Modul mit dem Beispieldienst hinzu:

angular.module('sampleServices', [])
  .service('util', function() {
    this.isNumber = function(num) {
      return !isNaN(num);
    };

    this.isDate = function(date) {
      return (date instanceof Date);
    };
  });
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Der folgende Code ist der beforeEach -Blocking in der Testdatei des Beispieldienstes:

module(function($provide) {
  $provide.service('util', function() {
    this.isNumber = jasmine.createSpy('isNumber').andCallFake(function(num) {
      // 模拟实现
    });
    this.isDate = jasmine.createSpy('isDate').andCallFake(function(num) {
      // 模拟实现
    });
  });
});

// 获取模拟服务的引用
var mockUtilSvc;

inject(function(util) {
  mockUtilSvc = util;
});
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Alternativ können wir die simulierte Implementierung des Dienstes zum oben definierten virtuellen Modul hinzufügen.

simulieren Sie die Methode, um zu Versprechen zurückzukehren

Eine End-to-End-Winkelanwendung kann schwierig sein, ohne Versprechen zu verwenden. Das Testen von Codeausschnitten, die auf Methoden beruhen, die das Rückkehrversprechen zur Herausforderung stellt. Ein normaler Jasminspion bewirkt, dass einige Testfälle fehlschlagen, da die zu testende Funktion ein Objekt mit der tatsächlichen Versprechungsstruktur erwartet.

asynchrone Methoden können mit einer anderen asynchronen Methode simuliert werden, die ein Versprechen mit einem statischen Wert zurückgibt. Betrachten Sie die folgenden Fabriken:

angular.module('mockingProviders',[])
  .provider('sample', function() {
    var registeredVals = [];

    this.register = function(val) {
      registeredVals.push(val);      
    };

    this.$get = function() {
      function getRegisteredVals() {
        return registeredVals;
      }

      return {
        getRegisteredVals: getRegisteredVals
      };
    };
  });
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Wir werden die getData() -Funktion in der obigen Fabrik testen. Wie wir sehen können, basiert es auf der Methode, dataSourceSvc getAllItems() zu bedienen. Wir müssen Dienste und Methoden simulieren, bevor wir die Funktionalität der getData() -Methode testen.

Der

$q Service verfügt über when() und reject() Methoden, mit denen die Verwendung statischer Werte auflösen oder abgelehnt werden können. Diese Methoden sind sehr nützlich, um Verspottungsmethoden zu testen, die das Versprechen zurückgeben. Der folgende Code -Snippet simuliert dataSourceSvc Fabrik:

module(function($provide) {
  $provide.provider('sample', function() {
    this.register = jasmine.createSpy('register');

    this.$get = function() {
      var getRegisteredVals = jasmine.createSpy('getRegisteredVals');

      return {
        getRegisteredVals: getRegisteredVals
      };
    };
  });
});

// 获取提供程序的引用
var sampleProviderObj;

module(function(sampleProvider) {
  sampleProviderObj = sampleProvider;
});
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

$q Versprechen vervollständigt seinen Betrieb nach dem nächsten Verdauungszyklus. Der Digest -Zyklus läuft in der tatsächlichen Anwendung kontinuierlich, jedoch nicht im Test. Daher müssen wir $rootScope.$digest() manuell anrufen, um das Versprechen durchzusetzen. Der folgende Code -Snippet zeigt einen Beispieltest:

angular.module('first', ['second', 'third'])
  // util 和 storage 分别在 second 和 third 中定义
  .service('sampleSvc', function(utilSvc, storageSvc) {
    // 服务实现
  });
Nach dem Login kopieren

Globale Objekte simulieren

globale Objekte stammen aus den folgenden Quellen:

  1. Objekte, die Teil des globalen "Fenster" -Objekts sind (z. B. Lokalstor, indexeddb, Mathematik usw.).
  2. Objekte, die von Bibliotheken von Drittanbietern erstellt wurden, wie JQuery, Unterstrich, Moment, Brise oder andere Bibliotheken.

standardmäßig können globale Objekte nicht simuliert werden. Wir müssen bestimmte Schritte ausführen, um sie simulatierbar zu machen.

Wir möchten möglicherweise keine mathematischen Objekte oder Versorgungsobjekte (erstellt von der Unterstrichbibliothek) simulieren, da ihre Operationen keine Geschäftslogik ausführen, die Benutzeroberfläche betreiben und nicht mit der Datenquelle kommunizieren. Objekte wie $ .Ajax, LocalStorage, Websockets, Breeze und Toastr müssen jedoch simuliert werden. Denn wenn diese Objekte nicht verspottet werden, führen sie ihre tatsächlichen Vorgänge bei der Durchführung von Unit -Tests durch, was zu unnötigen UI -Updates, Netzwerkaufrufen und manchmal im Testcode führen kann. _

Aufgrund der Abhängigkeitsinjektion ist jeder Teil des in Angular geschriebenen Codes prüfbar. Mit DI können wir jedes Objekt übergeben, das dem tatsächlichen Objekt -Shim folgt, nur damit der getestete Code bei der Ausführung nicht durchbricht. Wenn globale Objekte injiziert werden können, können sie simuliert werden. Es gibt zwei Möglichkeiten, globale Objekte injizierbar zu machen:

  1. Inject $window in den Service/Controller injizieren, der das globale Objekt benötigt und über $window auf das globale Objekt zugreift. Beispielsweise verwenden die folgenden Dienste LocalStorage über $window:
angular.module('sampleServices', [])
  .service('util', function() {
    this.isNumber = function(num) {
      return !isNaN(num);
    };

    this.isDate = function(date) {
      return (date instanceof Date);
    };
  });
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
  1. Erstellen Sie mit einem globalen Objekt einen Wert oder eine Konstante und injizieren Sie ihn, wo er benötigt wird. Zum Beispiel ist der folgende Code eine Konstante für Toastr:
module(function($provide) {
  $provide.service('util', function() {
    this.isNumber = jasmine.createSpy('isNumber').andCallFake(function(num) {
      // 模拟实现
    });
    this.isDate = jasmine.createSpy('isDate').andCallFake(function(num) {
      // 模拟实现
    });
  });
});

// 获取模拟服务的引用
var mockUtilSvc;

inject(function(util) {
  mockUtilSvc = util;
});
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Ich ziehe es vor, globale Objekte mit Konstanten anstelle von Werten zu wickeln, da Konstanten in Konfigurationsblöcke oder Anbieter injiziert werden können und Konstanten können nicht dekoriert werden.

Das folgende Code -Snippet zeigt die Simulation von LocalStorage und Toastr:

angular.module('mockingProviders',[])
  .provider('sample', function() {
    var registeredVals = [];

    this.register = function(val) {
      registeredVals.push(val);      
    };

    this.$get = function() {
      function getRegisteredVals() {
        return registeredVals;
      }

      return {
        getRegisteredVals: getRegisteredVals
      };
    };
  });
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Schlussfolgerung

Mock ist einer der wichtigsten Komponenten von Schreibabteilungstests in jeder Sprache. Wie wir gesehen haben, spielt die Abhängigkeitsinjektion eine wichtige Rolle bei der Prüfung und Simulation. Der Code muss so organisiert werden, dass seine Funktionalität leicht getestet werden kann. Dieser Artikel listet den häufigsten Satz von Objekten auf, die beim Testen von AngularJS -Anwendungen simulieren können. Der mit diesem Artikel bezogene Code kann von GitHub heruntergeladen werden.

FAQ von Spottabhängigkeiten in AngularJS -Tests (FAQ)

Was ist der Zweck der Verspottung von Abhängigkeiten bei AngularJS -Tests?

spöttische Abhängigkeiten bei AngularJS -Tests sind ein wichtiger Teil der Unit -Tests. Es ermöglicht Entwicklern, den getesteten Code zu isolieren und das Verhalten ihrer Abhängigkeiten zu simulieren. Auf diese Weise können Sie testen, wie Ihr Code mit seinen Abhängigkeiten interagiert, ohne sie tatsächlich anzurufen. Dies ist besonders nützlich, wenn Abhängigkeiten komplex, langsam oder Nebenwirkungen haben, die Sie während des Tests vermeiden möchten. Durch die Verspottung dieser Abhängigkeiten können Sie sich darauf konzentrieren, die Funktionalität Ihres Codes in einer kontrollierten Umgebung zu testen.

Wie erstellt man einen Scheinservice in AngularJs?

Erstellen eines Mock -Dienstes in AngularJS beinhaltet die Verwendung des $provide -Dienstes in der Modulkonfiguration. Sie können die $provide -Dienstmethoden value, factory oder service verwenden, um eine simulierte Implementierung eines Dienstes zu definieren. Hier ist ein grundlegendes Beispiel:

module(function($provide) {
  $provide.provider('sample', function() {
    this.register = jasmine.createSpy('register');

    this.$get = function() {
      var getRegisteredVals = jasmine.createSpy('getRegisteredVals');

      return {
        getRegisteredVals: getRegisteredVals
      };
    };
  });
});

// 获取提供程序的引用
var sampleProviderObj;

module(function(sampleProvider) {
  sampleProviderObj = sampleProvider;
});
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

In diesem Beispiel verwenden wir die $provide.value -Methode, um die simulierte Implementierung von myService zu definieren. Während des Tests wird dieser Scheinservice anstelle des tatsächlichen Dienstes verwendet.

(Bitte stellen Sie den Rest der FAQ -Fragen nacheinander aus Platzbeschränkungen, und ich werde mein Bestes geben, um präzise und klare Antworten zu geben.)

Das obige ist der detaillierte Inhalt vonVerspottete Abhängigkeiten in AngularJS -Tests. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Neueste Artikel des Autors
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage