2

我正在开发一个基于网络的 3D 游戏。我用TypeScript完全设置了我的项目。

我使用Angular设置了所有路由,并且我使用Three.js作为我的 3D 引擎。

最后,我有Mocha + Chai组合来使用名为typescript-require的特定插件来测试我的 TypeScript 。

我使用Systemjs作为我的JSPM包的导入器。

所以要设置阶段:(
出于示例目的,文件被剥离

Systemjs/JSPM 文件:jspmconfig.js

System.config({

  ...

  paths: {

    ...

    "github:*": "jspm_packages/github/*"

    ...

  },

  map: {

    ...

    "three.js": "github:mrdoob/three.js@master"

    ...

  }
});

节点文件:package.json

...

"scripts": {
  "test": "mocha --compilers ts:typescript-require ./source/**/*.spec.ts"
},

...

控制器文件QuestDetailCtrl.ts::

/// <reference path="../../../../../typings/tsd.d.ts" />

// Controller | Dashboard
export default class QuestDetailCtrl {

    ... 

    // Constructor
    constructor() { ... }

    renderer: THREE.WebGLRenderer = new THREE.WebGLRenderer(); // <-- This line uses a THREE instance.
}

注意 在我的应用程序中早一点的地方我已经导入了 Three.js,因此它在我的控制器中可用(这也可以正确编译为 ES5 并在浏览器中工作)。

摩卡测试文件QuestDetailCtrl.spec.ts

/// <reference path="../../../../../typings/tsd.d.ts" />

// Imports
import { assert, expect } from 'chai';
import QuestDetailCtrl from './QuestDetailCtrl';

// Describe
describe('QuestDetailCtrl', function() {

    // Shoulds
    it('should exist', () => {
        expect(QuestDetailCtrl).to.exist; // <-- WORKS
    });

    it('should initialize', () => {
        let instance = new QuestDetailCtrl(); // <-- DOES NOT WORK
    });

});

在最后一个文件QuestDetailCtrl.spec.ts中,我初始化了我的控制器(TypeScript 类)的一个新实例。

因为 Mocha 不知道 Three.js,所以这个测试在初始化我的控制器实例时失败了。

所以我的问题变成了:

我将如何在我的测试中模拟/导入 Three.js(或任何其他第三方库),以便 Mocha 知道它并能够测试/初始化它?

我想当我开始测试时,类似的情况也适用于 Angular,因此非常感谢您提供解决方案!

我已经遇到了解决方案,可以将数据import System from 'systemjs'设置metathree.js库中进行设置global系统的变量,但我无法让它工作。

谢谢!

4

2 回答 2

2

您不应在测试套件中创建供应商依赖项的实例,也不应创建已测试类依赖项的实例,只需使用例如sinonjs模拟它。

在这里你有我的例子它没有任何复杂的测试套件只是微不足道的一个(我会尽快添加一些更复杂的)但它有 Mocha & Chai & sinon + TypeScript + SystemJS + JSPM + Angular + ... :)

于 2015-10-10T16:19:55.997 回答
2

我现在可以考虑两种可能性。我将用 JS (es6) 编写它,因为我对 typescript 和 Jasmine 不太熟悉,但你可以很容易地将其转换为 mocha。

在测试中设置全局变量

//QuestDetailCtrl.spec.ts
import THREE from 'three';
window.THREE = THREE;
// or just mock it window.THREE = {}. Its usually not a good thing to 
// import whole external library in your tests. If you will mock them, 
// don't forget to reset your mock before each test if you need a fresh mock

在您的脚本中导入三个作为依赖项并在您的测试中模拟它

//QuestDetailCtrl.ts
import THREE from 'three';
export default class QuestDetailCtrl {
  constructor() { ... }

  renderer: THREE.WebGLRenderer = new THREE.WebGLRenderer(); // <-- This line uses a THREE instance.
}

//===================================================================
//QuestDetailCtrl.spec.ts
// be aware, Im using jasmine 2 here. Im passing done value in to function because mocking dependencies are async. Im not sure how this can be done in mocha

beforeAll(done => {
  System.delete('three');

  System.set('absolute/and/normalized/three/path', System.newModule({
    WebGLRenderer: ()=>{},
  }));
  System.import('absolute/and/normalized/path/QuestDetailCtrl').then(module=>{
    ComponentBuilder = module;
    done();
  });
});

希望那有帮助。

于 2015-11-03T10:13:29.037 回答