2017-10-05 1 views
2

Je travaille pour obtenir des classes de Typescript testées avec Jasmine. J'ai créé quelques classes qui composent entre eux par des déclarations du module:Qu'est-ce que cela signifie dans un test de jasmin: Uncaught TypeError: Le prototype de l'objet ne peut être qu'un objet ou null: undefined?

module xxx.DeviceData { 
    export class ConsoleListener extends DataListener { 
     constructor() { 
      super("ConsoleListener"); 
     } 

     addData(data: string) { 
      console.log(this.title + ": " + data); 
     } 

     clear() { 
      console.clear(); 
     } 
    } 
} 

Je compose la teste Jasmine ensemble de la même façon:

module xxx.DeviceData { 
describe('ConsoleListener test', function() { 
    var consoleListener, 
     consoleListenerObj; 

    beforeEach(() => { 
     consoleListener = jasmine.createSpy("consoleListener"); 

     consoleListenerObj = jasmine.createSpyObj('consoleListenerObj', ['onSuccess', 'onFailure', 'addData', 'clear']); 
     consoleListenerObj.onSuccess(); 
     consoleListenerObj.onFailure(); 
     consoleListenerObj.addData(); 
     consoleListenerObj.clear(); 
    }); 

    it('test#1 columnDefinition defined', function() { 
     let consoleListener = new ConsoleListener(); 

     expect(consoleListener).not.toBeNull(); 
    }); 

    it('test#2 call onSuccess', function() { 
     expect(consoleListenerObj.onSuccess).toHaveBeenCalled(); 
    }); 

    it('test#3 call onFailure', function() { 
     expect(consoleListenerObj.onFailure).toHaveBeenCalled(); 
    }); 

    it('test#4 call addData', function() { 
     expect(consoleListenerObj.addData('123')); 
    }); 

    it('test#5 call clear', function() { 
     expect(consoleListenerObj.clear()); 
    }); 
}); 
} 

Tout cela transpiles parfaitement. Lorsque je tente d'exécuter le test, je reçois cette erreur

Uncaught TypeError: prototype d'objet ne peut être un objet ou nul: non défini à Scripts/DeviceData/ConsoleListener.js: 5: 27

Quelque chose va mal sur la ligne 5 du JS transpilé, non? Voici ce que:

var __extends = (this && this.__extends) || (function() { 
    var extendStatics = Object.setPrototypeOf || 
     ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || 
     function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; 
    return function (d, b) { 
     extendStatics(d, b); 
     function __() { this.constructor = d; } 
     d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); 
    }; 
})(); 
var xxx; 
(function (xxx) { 
    var DeviceData; 
    (function (DeviceData) { 
     var ConsoleListener = (function (_super) { 
      __extends(ConsoleListener, _super); 
      function ConsoleListener() { 
       return _super.call(this, "ConsoleListener") || this; 
      } 
      ConsoleListener.prototype.addData = function (data) { 
       console.log(this.title + ": " + data); 
      }; 
      ConsoleListener.prototype.clear = function() { 
       console.clear(); 
      }; 
      return ConsoleListener; 
     }(DeviceData.DataListener)); 
     DeviceData.ConsoleListener = ConsoleListener; 
    })(DeviceData = xxx.DeviceData || (xxx.DeviceData = {})); 
})(xxx|| (xxx= {})); 
//# sourceMappingURL=ConsoleListener.js.map 

Et bien sûr, la ligne 5 semble parler d'objets et de prototypes.

J'ai essayé différentes façons de faire dialoguer les modules entre eux, mais cette approche de module est la seule que je peux utiliser pour fonctionner de manière cohérente. Y a-t-il quelque chose qui manque dans le contexte du karma/jasmin qui doit être passé ici?

Voici mon karma.config:

module.exports = function (config) { 
     config.set({ 

      frameworks: ["jasmine","karma-typescript"], 

      preprocessors: { 
       "Scripts/**/*.ts": ["karma-typescript"] 
      }, 

      files: [ 
       'Scripts/DeviceData/*.ts', 
       'Scripts/UnitTests/*.spec.ts' 
      ], 

      exclude: [ 
       'Scripts/**/NodeJSDataSocket.ts' 
      ], 
      reporters: ["progress", "karma-typescript"], 

      //reporters: ["dots", "karma-typescript"], 

      browsers: ["Chrome"], 
      karmaTypescriptConfig: { 
       compilerOptions: { 
        "module": "commonjs", 
        "sourceMap": true, 
        "target": "es5" 
"moduleResolution": "classic", 
"noImplicitAny": false 
       }, 
       tsconfig: "./tsconfig.json", 
      }, 
     }); 
    }; 

Répondre

2

L'erreur ressemble à cela vient de la tapuscrit fonction extends injectent lorsque vous héritez d'une classe super.

En regardant le code, je dirais que votre DataListener n'est pas disponible pour vous lorsque vous l'utilisez:

extends DataListener 

Il est sans doute pas totalement absente, sinon le compilateur vous avertit - il est donc soit pas inclus (c.-à-d. chargé) quand Jasmine court, ou vous avez des choses en train de charger dans le désordre. Mettez-les dans l'ordre et, espérons-le, ... joie!

 files: [ 
      'Scripts/DeviceData/DataListener.ts', 
      'Scripts/DeviceData/ConsoleListener.ts', 
      'Scripts/UnitTests/*.spec.ts' 
     ], 
+0

Excellent - cela semble évident rétrospectivement. Ma première pensée était que ça n'était pas inclus dans le fichier karma.config, mais ça devrait être - j'ai posté ça dessus. D'autres idées sur pourquoi cela ne serait pas inclus? En attendant, j'ai un fichier autonome que je peux isoler et tester pour le confirmer. –

+0

Oui, ça a marché, donc c'est définitivement l'héritage là-bas. –

+0

Dans quel fichier 'DataListener' se trouve-t-il? – Fenton

1

Le __extends() function est généré par le compilateur de la machine à écrire pour gérer l'héritage de classe. b signifie classe de base et d est pour la classe dérivée. Donc, le problème est que la classe de base DataListener est manquante. Vérifiez la façon dont vous compilez et regroupez les scripts. Un espace de noms (voir le mot-clé module) peut être défini sur plusieurs fichiers, mais leur regroupement/groupement doit être géré manuellement ou avec le compiler option --outFile.