typescript - Hva betyr dette i en jasmine-test: Uncaught TypeError: Object prototype may only be an Object or null: undefined?


Jeg jobber med å få noen Typescript-klasser testet med Jasmine. Jeg har laget noen klasser som komponerer med hverandre via moduldeklarasjoner:

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

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

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

Jeg komponerer Jasmine-testene på samme måte:

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

Alt dette transilerer perfekt. Når jeg prøver å kjøre testen, får jeg denne feilen

Ufanget TypeError: Objektprototype kan bare være et objekt eller null: undefined ved Scripts/DeviceData/ConsoleListener.js:5:27

Noe går galt på linje 5 i den transpilerte JS-en, ikke sant? Her er den:

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

Og ganske riktig, linje 5 ser ut til å snakke om objekter og prototyper.

Jeg har prøvd forskjellige måter å få modulene til å kommunisere med hverandre på, men denne modultilnærmingen er den eneste jeg kan få til å fungere konsekvent. Er det noe som mangler i karma/jasmine-konteksten som må sendes her?

Her er min 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",
            },
        });
    };

Svar #1

Feilen ser ut til å komme fra extends-funksjonen som TypeScript injiserer når du arver fra en superklasse.

Når jeg ser på koden, vil jeg si at din DataListener ikke er tilgjengelig for deg når du bruker den:

extends DataListener 

Det er sannsynligvis ikke helt fraværende, ellers ville kompilatoren advart deg - så det er enten ikke inkludert (dvs. lastet) når Jasmine kjører, eller så har du ting som lastes i feil rekkefølge.

Få dem i orden og forhåpentligvis... glede!

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

Svar #2

Funksjonen __extends() genereres av TypeScript-kompilatoren for å håndtere klassearv. b betyr baseklasse og d er for avledet klasse. Så problemet er at baseklassen DataListener mangler. Sjekk måten du kompilerer og bundler skriptene på. Ett navnerom (jf. module-nøkkelordet) kan defineres over flere filer, men samlingen/bunlingen deres må håndteres manuelt eller med kompilatoralternativet --outFile.

Relaterte artikler