Ionic单元测试前期配置
2017-09-09 本文已影响0人
Gary嘉骏
一、安装依赖:
-
npm i webpack -g
-
npm i karma-cli -g
-
npm i @ionic/cli-build-ionic-angular @ionic/cli-plugin-cordova @types/jasmine@2.5.36 @types/node angular2-template-loader html-loader istanbul-instrumenter-loader jasmine jasmine-spec-reporter karma karma-chrome-launcher karma-coverage-istanbul-reporter karma-jasmine karma-jasmine-html-reporter karma-sourcemap-loader karma-webpack null-loader protractor ts-loader ts-node --save-dev
-
安装谷歌浏览器(测试报告会自动打开谷歌浏览器显示)
二、配置文件
1. 在 src内新建mocks.ts,内容如下:
/* tslint:disable */
// IONIC:
import { EventEmitter} from '@angular/core';
import { FormBuilder } from '@angular/forms';
export class AlertMock {
public create(): any {
let rtn: Object = {};
rtn['present'] = (() => true);
return rtn;
}
// function actually on the AlertClass (not AlertController), but using these interchangably for now
public dismiss(): Promise<{}> {
return new Promise(function(resolve: Function): void {
resolve();
});
}
}
export class ToastMock {
public create(): any {
let rtn: Object = {};
rtn['present'] = (() => true);
return rtn;
}
}
export class ConfigMock {
public get(): any {
return '';
}
public getBoolean(): boolean {
return true;
}
public getNumber(): number {
return 1;
}
public setTransition(): void {
return;
}
}
export class FormMock {
public register(): any {
return true;
}
}
export class NavMock {
public pop(): any {
return new Promise(function(resolve: Function): void {
resolve();
});
}
public push(): any {
return new Promise(function(resolve: Function): void {
resolve();
});
}
public getActive(): any {
return {
'instance': {
'model': 'something',
},
};
}
public setRoot(): any {
return true;
}
public popToRoot(): any {
return true;
}
}
export class PlatformMock {
public ready(): Promise<{String}> {
return new Promise((resolve) => {
resolve('READY');
});
}
public registerBackButtonAction(fn: Function, priority?: number): Function {
return (() => true);
}
public hasFocus(ele: HTMLElement): boolean {
return true;
}
public doc(): HTMLDocument {
return document;
}
public is(): boolean {
return true;
}
public getElementComputedStyle(container: any): any {
return {
paddingLeft: '10',
paddingTop: '10',
paddingRight: '10',
paddingBottom: '10',
};
}
public onResize(callback: any) {
return callback;
}
public registerListener(ele: any, eventName: string, callback: any): Function {
return (() => true);
}
public win(): Window {
return window;
}
public raf(callback: any): number {
return 1;
}
public timeout(callback: any, timer: number): any {
return setTimeout(callback, timer);
}
public cancelTimeout(id: any) {
// do nothing
}
public getActiveElement(): any {
return document['activeElement'];
}
}
export class StorageMock {
public get(key: string): Promise<{}> {
return new Promise((resolve: Function) => {
resolve({});
});
}
public set(key: string, value: string): Promise<{}> {
return new Promise((resolve: Function) => {
resolve({key: key, value: value});
});
}
public remove(key: string): Promise<{}> {
return new Promise((resolve: Function) => {
resolve({key: key});
});
}
public query(): Promise<{ res: { rows: Array<{}> }}> {
return new Promise((resolve) => {
resolve({
res: {
rows: [{}]
}
});
});
}
}
export class MenuMock {
public close(): any {
return new Promise((resolve: Function) => {
resolve();
});
}
}
export class AppMock {
public getActiveNav(): NavMock {
return new NavMock();
}
}
/* tslint:enable */
2.根目录下新建文件夹 test-config,插入以下3个文件
1. karma.conf.js:
var webpackConfig = require('./webpack.test.js');
module.exports = function (config) {
var _config = {
basePath: '',
frameworks: ['jasmine'],
files: [
{pattern: './karma-test-shim.js', watched: true}
],
preprocessors: {
'./karma-test-shim.js': ['webpack', 'sourcemap']
},
webpack: webpackConfig,
webpackMiddleware: {
stats: 'errors-only'
},
webpackServer: {
noInfo: true
},
browserConsoleLogOptions: {
level: 'log',
format: '%b %T: %m',
terminal: true
},
coverageIstanbulReporter: {
reports: [ 'html', 'lcovonly' ],
fixWebpackSourcePaths: true
},
reporters: config.coverage ? ['kjhtml', 'dots', 'coverage-istanbul'] : ['kjhtml', 'dots'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Chrome'],
singleRun: false
};
config.set(_config);
};
2. karma-test-shim.js
Error.stackTraceLimit = Infinity;
require('core-js/es6');
require('core-js/es7/reflect');
require('zone.js/dist/zone');
require('zone.js/dist/long-stack-trace-zone');
require('zone.js/dist/proxy');
require('zone.js/dist/sync-test');
require('zone.js/dist/jasmine-patch');
require('zone.js/dist/async-test');
require('zone.js/dist/fake-async-test');
var appContext = require.context('../src', true, /\.spec\.ts/);
appContext.keys().forEach(appContext);
var testing = require('@angular/core/testing');
var browser = require('@angular/platform-browser-dynamic/testing');
testing.TestBed.initTestEnvironment(browser.BrowserDynamicTestingModule, browser.platformBrowserDynamicTesting());
3. webpack.test.js
var webpack = require('webpack');
var path = require('path');
module.exports = {
devtool: 'inline-source-map',
resolve: {
extensions: ['.ts', '.js']
},
module: {
rules: [
{
test: /\.ts$/,
loaders: [
{
loader: 'ts-loader'
} , 'angular2-template-loader'
]
},
{
test: /.+\.ts$/,
exclude: /(index.ts|mocks.ts|\.spec\.ts$)/,
loader: 'istanbul-instrumenter-loader',
enforce: 'post',
query: {
esModules: true
}
},
{
test: /\.html$/,
loader: 'html-loader'
},
{
test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/,
loader: 'null-loader'
}
]
},
plugins: [
new webpack.ContextReplacementPlugin(
// The (\\|\/) piece accounts for path separators in *nix and Windows
/angular(\\|\/)core(\\|\/)(esm(\\|\/)src|src)(\\|\/)linker/,
root('./src'), // location of your src
{} // a map of your routes
)
]
};
function root(localPath) {
return path.resolve(__dirname, localPath);
}
三、添加命令行到package.json
- 在scripts项最后添加:
"test": "karma start ./test-config/karma.conf.js --coverage"
然后就可以使用npm test 运行
四、单元测试文件的注意事项
-
文档名格式为 *.spec.ts
-
避免typescript 检测报错项目启动不了, 在tsconfig.json 内的exclude加入 "src/*/.spec.ts",
-
与angular2 单元测试文档 相比,对组件的测试需要另外配置以下平台内容:
import { App, Config, Form, IonicModule, Keyboard, DomController, MenuController, NavController, Platform, NavParams, GestureController } from 'ionic-angular';
import { ConfigMock, PlatformMock, NavMock } from ‘mocks的相对路径’;
- TestBed.configureTestingModule如下配置:
TestBed.configureTestingModule({
declarations: [‘XX’], // 需要测试的模块名
providers: [
App, DomController, Form, Keyboard, NavController,GestureController,ValidateService,
{provide: Config, useClass: ConfigMock},
{provide: Platform, useClass: PlatformMock},
{provide: NavParams, useClass: NavMock}
],
imports: [
IonicModule,
],
})
简单例子
在src文件内新建文件 1st.spec.ts
describe('1st tests', () => {
it('true is true', () => expect(true).toBe(true));
});
然后运行 npm test 即可
相关
Done!
如果觉得文章对你有点用的话,麻烦拿出手机,这里有一个你我都有的小福利(每天一次): 打开支付宝首页搜索“8601304”,即可领红包。谢谢支持