开发者问题收集

在 jasmine 测试中这是什么意思:未捕获的类型错误:对象原型可能只是一个对象或为空:未定义?

2017-10-05
1599

我正在努力使用 Jasmine 测试一些 Typescript 类。我创建了一些通过模块声明相互组合的类:

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

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

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

我正在以相同的方式组合 Jasmine 测试:

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

所有这些都完美地转译了。当我尝试执行测试时,我收到此错误

Uncaught TypeError:对象原型可能只是一个对象或 null:在 Scripts/DeviceData/ConsoleListener.js:5:27 处未定义

转译后的 JS 的第 5 行出了问题,对吗?就是这样:

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

果然,第 5 行似乎在谈论对象和原型。

我尝试过不同的方法让模块相互通信,但这种模块方法是我唯一能够始终如一地工作的方法。karma / jasmine 上下文中是否缺少需要在此处传递的内容?

这是我的 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",
            },
        });
    };
2个回答

错误看起来像是来自从超类继承时 TypeScript 注入的 extends 函数。

查看代码,我会说当您使用 DataListener 时它不可用:

extends DataListener 

它可能没有完全丢失,否则编译器会警告您 - 因此在 Jasmine 运行时它要么未包含(即加载),要么加载顺序不正确。

将它们整理好,希望...快乐!

        files: [
            'Scripts/DeviceData/DataListener.ts',
            'Scripts/DeviceData/ConsoleListener.ts',
            'Scripts/UnitTests/*.spec.ts' 
        ],
Fenton
2017-10-05

TypeScript 编译器生成 __extends() 函数 来处理类继承。 b 表示基类, d 表示派生类。因此,问题在于缺少基类 DataListener 。检查您编译和捆绑脚本的方式。一个命名空间(参见 module 关键字)可以在多个文件中定义,但它们的收集/捆绑必须手动处理或使用 编译器选项 --outFile

Romain Deneau
2017-10-05