如何测试 Mocha & Chai + TypeScript + SystemJS + JSPM + Angular + Three.js
How to test Mocha & Chai + TypeScript + SystemJS + JSPM + Angular + Three.js
我正在开发基于网络的 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 class)。
因为 Mocha 不知道 Three.js,所以这个测试在初始化我的控制器实例时失败了。
所以我的问题变成了:
我如何 mock/import Three.js (或任何其他第三方库)在我的测试中,以便摩卡知道它并能够 test/initialize它?
我想当我开始测试时,类似的情况也适用于 Angular,因此非常感谢您提供解决方案!
我已经遇到了 import System from 'systemjs'
并将 meta
数据设置到 three.js
库以设置 global
系统变量的解决方案,但我做不到让它工作。
谢谢!
您不应在测试套件中创建供应商依赖项的实例,也不应创建已测试 class 依赖项的实例,只需使用 sinonjs.[=12 等模拟它即可=]
这是我的 example 它没有任何复杂的测试套件,只有一个简单的测试套件(我会尝试尽快添加一些更复杂的)但它有 Mocha & Chai & sinon + TypeScript + SystemJS + JSPM + Angular + ... :)
暂时想到两种可能。我会用 JS (es6) 编写它,因为我不太熟悉 typescript 和 Jasmine,但是你可以很容易地将它转换成 mocha。
set global variable in your test
//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
import three as dependency in your script and mock it in your test
//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();
});
});
希望对您有所帮助。
我正在开发基于网络的 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 class)。
因为 Mocha 不知道 Three.js,所以这个测试在初始化我的控制器实例时失败了。
所以我的问题变成了:
我如何 mock/import Three.js (或任何其他第三方库)在我的测试中,以便摩卡知道它并能够 test/initialize它?
我想当我开始测试时,类似的情况也适用于 Angular,因此非常感谢您提供解决方案!
我已经遇到了 import System from 'systemjs'
并将 meta
数据设置到 three.js
库以设置 global
系统变量的解决方案,但我做不到让它工作。
谢谢!
您不应在测试套件中创建供应商依赖项的实例,也不应创建已测试 class 依赖项的实例,只需使用 sinonjs.[=12 等模拟它即可=]
这是我的 example 它没有任何复杂的测试套件,只有一个简单的测试套件(我会尝试尽快添加一些更复杂的)但它有 Mocha & Chai & sinon + TypeScript + SystemJS + JSPM + Angular + ... :)
暂时想到两种可能。我会用 JS (es6) 编写它,因为我不太熟悉 typescript 和 Jasmine,但是你可以很容易地将它转换成 mocha。
set global variable in your test
//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
import three as dependency in your script and mock it in your test
//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();
});
});
希望对您有所帮助。