Der Testservice im Angular Returns-Modul ist nicht definiert

127

Ich versuche, den Standard-Serviceeinheitentest in meinem Projekt auszuführen (entnommen aus dem Angular Seed-Projekt auf GitHub), erhalte jedoch weiterhin die Fehlermeldung "Modul ist nicht definiert".

Ich habe gelesen, dass es etwas mit der Reihenfolge der referenzierten JavaScript-Dateien zu tun haben könnte , aber ich kann es scheinbar nicht zum Laufen bringen, also kann hoffentlich einer von Ihnen helfen.

Meine Konfiguration für den Test sieht folgendermaßen aus:

basePath = '../';

files = [
'public / javascripts / lib / jquery-1.8.2.js',
'public / javascripts / lib / angular.js',
'public / javascripts / lib / angular- .js',
'public / app.js. ',
' public / controller /
.js ',
' public / directives.js ',
' public / filter.js ',
' public / services.js ',
JASMINE,
JASMINE_ADAPTER,
' public / javascripts / lib / angle- mocks . js ',
' test / unit / *. js '];

autoWatch = true;

browser = ['Chrome'];

junitReporter = {outputFile: 'test_out / unit.xml', suite: 'unit'};

Der Service sieht wie folgt aus:

angular.module('myApp.services', []).
  value('version', '0.1');

Der Test sieht folgendermaßen aus:

'use strict';

describe('service', function() {
  beforeEach(module('myApp.services'));


  describe('version', function() {
    it('should return current version', inject(function(version) {
      expect(version).toEqual('0.1');
    }));
  });
});

Und der Fehler beim Ausführen des Tests durch testacular ist folgender:

ReferenceError: Modul ist nicht definiert

Dofs
quelle
2
Kannst du dein Projekt irgendwo teilen? Ich könnte helfen können. Haben Sie versucht, die DEBUG-Ebene für testacular zu aktivieren, um zu sehen, welche Dateien basierend auf Ihrer Konfiguration tatsächlich geladen werden? Im Moment ist der verdächtige Teil dieses Muster: public / javascripts / lib / angular-.js - was sollte dazu passen?
pkozlowski.opensource
@ JohnDoe Danke, das hat funktioniert. Wenn Sie eine Antwort hinzufügen, werde ich sie als gelöst markieren. Der Grund war, dass ich das Seed-Projekt verfolgte, das es so machte und das funktionierte. Ich weiß nicht, ob es daran liegt, dass es eine frühere Version war.
Dofs
@Dofs Sind "'public / javascripts / lib / angle-.js'" und "'public / controller / .js'" Tippfehler?
Ryan O'Neill
@ RyanO'Neill sorry, ja das war ein Tippfehler.
Dofs

Antworten:

260

Ihnen fehlt die Datei angle-mocks.js .

John Doe
quelle
8
Beachten Sie, dass angular.moduleund angular.mock.modulesind nicht gleich. Die window.moduleFunktion ist ein Alias ​​für angular.mock.module. Weitere Informationen finden Sie in dieser Antwort .
Tim Schaub
Wie im vorherigen Kommentar angegeben, ist angle.module kein Alias ​​für angle.mock.module.
Filippo De Luca
7
Diese Antwort wäre viel nützlicher, wenn sie Ratschläge zur Bereitstellung dieser Datei geben würde. Ich musste Bower installieren, dann NgMocks.
Isherwood
4
Die Antwort liefert nur einen Teil der Lösung. Dies ist eigentlich ein Kommentar und keine Erklärung. Einige der folgenden Antworten sind viel detaillierter.
Gerome Bochmann
1
Für Anfänger müssen Sie einen Verweis auf angular-mocksin die karma.conf.jsDatei einfügen und die Tests über Karma und nicht über Jasmine ausführen. Auf diese Weise werden beim Ausführen von Karma die angular-mocksErweiterungen erfasst und in die Umgebung integriert.
Luke
41

Ich hatte das gleiche Problem und verstand, warum es nicht funktionierte: Auf das Javascript jasmine.js muss VOR der Datei angle-mocks.js verwiesen werden. In der Tat prüft die angle-mocks.js, ob Jasmine geladen ist, und nur wenn dies der Fall ist, wird die Modulfunktion zum Fenster hinzugefügt.

Hier ist ein Auszug aus Angular Mocks-Code:

(Bearbeiten Sie nach den wenigen Kommentaren zu 'Hacking', die ich unten hatte: Dies ist nur ein Auszug aus dem Code, dies ist nicht etwas, das Sie selbst schreiben müssen, es ist bereits da!)

window.jasmine && (function(window) {

[...]

  window.module = angular.mock.module = function() {
    var moduleFns = Array.prototype.slice.call(arguments, 0);
    return isSpecRunning() ? workFn() : workFn;
    /////////////////////
    [...]
  };

Kurz gesagt: Referenzieren Sie einfach Ihre jasmine.js vor angle-mocks.js und los geht's.

Antoine Jaussoin
quelle
Dies kann auch behoben werden, indem sichergestellt wird, dass die Jasmin-Javascript-Dateien vor Angular-Mocks geladen werden. Sauberere Lösung als hackige Änderungen, um Dinge zum Laufen zu bringen.
Foomip
@foomip Wer hat vorgeschlagen, hackige Änderungen vorzunehmen?
Stephen
Sie haben im Wesentlichen einen Hack in Ihre App eingefügt, um sicherzustellen, dass die Dinge korrekt geladen werden - und ich habe nicht gemein gehackt (es ist nichts Falsches daran, wie Sie diesen Codeausschnitt geschrieben haben), aber was passiert, wenn ein Update auf Jasmin oder etwas anderes führt dazu, dass das Snippet von Ihnen kaputt geht oder nicht mehr wie erwartet funktioniert? Es könnte oder könnte nicht passieren, aber das ist eine Haftung in Ihrem Code, die jetzt vermieden werden könnte, finden Sie nicht?
Foomip
@foomip: Ich bin mir nicht sicher, worauf Sie sich beziehen, aber wenn es um meinen obigen Code geht, wurde dieser nicht von mir geschrieben, ich zitiere ihn nur, um das Problem zu erklären. Der Code ist Teil von Angular-Mocks. Bei der Korrektur wird lediglich eine Datei vor der anderen referenziert.
Antoine Jaussoin
36

Die window.moduleFunktion kommt in angular-mocks.js und ist eine Abkürzung für angular.mock.module. Wie in den Dokumenten erwähnt , modulefunktioniert die Funktion nur mit Jasmine.

Bei Verwendung von Testacular wird die folgende Beispielkonfigurationsdatei geladen angular-mocks.js.

/** example testacular.conf.js */

basePath = '../';
files = [
  JASMINE,
  JASMINE_ADAPTER,
  'path/to/angular.js',
  'path/to/angular-mocks.js',   // for angular.mock.module and inject.
  'src/js/**/*.js',             // application sources
  'test/unit/**/*.spec.js'      // specs
];
autoWatch = true;
browsers = ['Chrome'];

Und wie an anderer Stelle vorgeschlagen, können Sie Testacular mit Debug-Protokollierung ausführen, um zu sehen, welche Skripte geladen sind (dasselbe können Sie auch im Inspektor sehen):

testacular --log-level debug start config/testacular.conf.js

Die angular.mock.injectDokumente enthalten ein ziemlich vollständiges Beispiel.

Tim Schaub
quelle
Vielleicht erwähnenswert, dass modulejetzt auch mit Mokka funktioniert
Robin-Hoodie
11

Wir verwenden 'Modul' ohne 'Winkel' in unseren Unit-Tests und es funktioniert gut.

CoffeeScript:

describe 'DiscussionServicesSpec', ->
    beforeEach module 'DiscussionServices'
    beforeEach inject ... etc.

welches kompiliert zu

JavaScript:

describe('DiscussionServices', function() {
    beforeEach(module('DiscussionServices'));
    beforeEach(inject(function ... etc.

Das einzige Mal, dass ich so etwas wie den von Ihnen beschriebenen Fehler sehe, ist, wenn in der Datei testacular.conf.js die Datei angle-mocks.js nicht im Dateibereich aufgeführt ist, bevor die Spezifikationen versuchen, 'module' zu verwenden. Wenn ich es nach meinen Tests in die Liste 'Dateien' schreibe, bekomme ich

ReferenceError: Can't find variable: module

(Unsere Tests werden über PhantomJS durchgeführt.)

Ryan O'Neill
quelle
2
Die Schlussfolgerung ist, dass Winkelverspottungen eine Voraussetzung sind.
Adrien
3

Ich hatte angular-mocks.js in meine Karma-Konfiguration aufgenommen, bekam aber immer noch den Fehler. Es stellt sich heraus, dass die Reihenfolge im Dateiarray wichtig ist. (duh) Genau wie im Kopf eines HTML-Dokuments, wenn ein Skript eckig aufruft, bevor es definiert ist, und ein Fehler auftritt. Also musste ich nur meine app.js nach angular.js und angular-mocks.js einfügen.

Erik
quelle
0

Wenn Sie Yeoman und seinen Winkelgenerator verwenden, wird dieser Fehler wahrscheinlich angezeigt. Besonders wenn Sie das Tutorial (._.) Ausführen, habe
ich es behoben, indem ich die Datei angle-mocks.js aus dem Verzeichnis bower_components / angle-mocks in das Verzeichnis test / mock kopiert habe. Natürlich müssen Sie sicherstellen, dass Ihre Datei karma.conf.js korrekt konfiguriert ist.
Schöne Grüße!

alxU
quelle
0

Ich hatte das gleiche Problem, als ich so etwas tat var module = angular.module('my',[]). Ich musste sicherstellen, dass es von IIFE umgeben war

Jackie
quelle