shark-test

1.0.4 • Public • Published

shark-test

为 shark 项目提供搭建测试环境的工具。

目录

一、安装

$ npm install --save-dev shark-test

二、安装测试相关的依赖

$ npm install --save classlist
$ npm install --save @types/jasmine

三、添加执行测试指令

在package.json文件中,添加测试指令

 
{
    "scripts": {
        "test": "./node_modules/shark-test/dist/src/index.js test"
    },
}
 

四、初始化配置文件

执行以下初始化命令,自动创建四个测试相关的配置文件

 
st init
 

或者

 
shark-test init
 

五、测试工具配置文件说明

在项目根目录下创建配置文件shark-test-conf.json,所有配置项都设了默认值

{
    //--
    "basePath": "src/main/webapp",
    // (.spec.ts)
    "main": "test.ts",
    // polyfills
    "polyfills": "polyfills",
    // karma
    "configFile": "karma.conf.js",
    // 
    "componentPath": "app",
    // 
    "assets": ["assets", "favicon.ico"],
    // 
    "indexTemplate": "index.ejs"
}

测试入口文件

在配置文件中设置的basePath路径下添加用于测试入口文件test.ts

 
// This file is required by karma.conf.js and loads recursively all the .spec and framework files
import "zone.js/dist/long-stack-trace-zone";
import "zone.js/dist/proxy";
import "zone.js/dist/sync-test";
import "zone.js/dist/jasmine-patch";
import "zone.js/dist/async-test";
import "zone.js/dist/fake-async-test";
 
import { getTestBed } from '@angular/core/testing';
 
import {
    BrowserDynamicTestingModule,
    platformBrowserDynamicTesting
} from '@angular/platform-browser-dynamic/testing';
 
declare const require: any;
 
// First, initialize the Angular testing environment.
getTestBed().initTestEnvironment(
    BrowserDynamicTestingModule,
    platformBrowserDynamicTesting()
);
// Then we find all the tests.
const context = require.context('./', true, /\.spec\.ts$/);
// And load the modules.
context.keys().map(context);
 

测试环境的polyfills.ts

在配置文件中设置的basePath路径下添加用于测试环境的polyfills.ts文件

/**
 * This file includes polyfills needed by Angular and is loaded before the app.
 * You can add your own extra polyfills to this file.
 *
 * This file is divided into 2 sections:
 *   1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
 *   2. Application imports. Files imported after ZoneJS that should be loaded before your main
 *      file.
 *
 * The current setup is for so-called "evergreen" browsers; the last versions of browsers that
 * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
 * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
 *
 * Learn more in https://angular.io/docs/ts/latest/guide/browser-support.html
 */
 
/***************************************************************************************************
 * BROWSER POLYFILLS
 */
 
/** IE9, IE10 and IE11 requires all of the following polyfills. **/
import 'core-js/es6/symbol';
import 'core-js/es6/object';
import 'core-js/es6/function';
import 'core-js/es6/parse-int';
import 'core-js/es6/parse-float';
import 'core-js/es6/number';
import 'core-js/es6/math';
import 'core-js/es6/string';
import 'core-js/es6/date';
import 'core-js/es6/array';
import 'core-js/es6/regexp';
import 'core-js/es6/map';
import 'core-js/es6/weak-map';
import 'core-js/es6/set';
 
/** IE10 and IE11 requires the following for NgClass support on SVG elements */
import 'classlist.js';  // Run `npm install --save classlist.js`.
 
/** IE10 and IE11 requires the following for the Reflect API. */
import 'core-js/es6/reflect';
 
 
/** Evergreen browsers require these. **/
// Used for reflect-metadata in JIT. If you use AOT (and only Angular decorators), you can remove.
import 'core-js/es7/reflect';
 
 
/**
 * Required to support Web Animations `@angular/platform-browser/animations`.
 * Needed for: All but Chrome, Firefox and Opera. http://caniuse.com/#feat=web-animation
 **/
// import 'web-animations-js';  // Run `npm install --save web-animations-js`.
 
 
 
/***************************************************************************************************
 * Zone JS is required by default for Angular itself.
 */
import 'zone.js/dist/zone';  // Included with Angular CLI.
/***************************************************************************************************
 * APPLICATION IMPORTS
 */
 

karma配置文件

在项目根目录下创建karma配置文件karma.conf.js

 
// Karma configuration file, see link for more information
// https://karma-runner.github.io/1.0/config/configuration-file.html
 
module.exports = function (config) {
  config.set({
    basePath: '',
    frameworks: ['jasmine', 'shark'],
    plugins: [
      require('karma-jasmine'),
      require('karma-chrome-launcher'),
      require('karma-jasmine-html-reporter'),
      require('karma-coverage-istanbul-reporter'),
      require('shark-test/dist/src/plugin/karma')
    ],
    client: {
      clearContext: false // leave Jasmine Spec Runner output visible in browser
    },
    coverageIstanbulReporter: {
      reports: ['html', 'lcovonly'],
      fixWebpackSourcePaths: true
    },
    reporters: ['progress', 'kjhtml'],
    port: 9888,
    colors: true,
    logLevel: config.LOG_INFO,
    autoWatch: true,
    browsers: ['Chrome'],
    singleRun: false
  });
};
 

六、使用

运行测试代码

 
npm run test
 

或者

 
st test
 

或者

 
shark-test test
 

七、FAQ

八、angular测试手册

各类测试说明:

一、Component(带输入输出的组件、带路由的组件、带依赖的组件、嵌套组件)

  1. 组件类测试

像测试服务类一样测试组件类,单独测试组件类本身而不必涉及DOM。

例子1:下面是一个列表组件ProduceScheduleComponent(带路由的组件、带依赖的组件、嵌套组件)

import { Component, ViewChild } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
import { ProduceScheduleService } from './produce-schedule.service';
@Component({
    styleUrls: ['./produce-schedule.component.scss'],
    templateUrl: './produce-schedule.component.html'
})
 
export class ProduceScheduleComponent {
    purchaseOrderList: Array<any>;//采购单列表
    pagination: any;
 
    constructor(
        private router: Router,
        private route: ActivatedRoute,
        private produceScheduleService: ProduceScheduleService
    ) {
    }
 
    ngOnInit() {
        let params={
          page:1,
          size:20
        }
        this.getPurchaseList(params)
    }
 
    getPurchaseList(params) {
        this.produceScheduleService.getProceedingList(params).then(data => {
            this.purchaseOrderList = data.result
            this.pagination = data.pagination
        }).catch(err => { })
    }
}
 

组件对应的测试代码

import { TestBed, async } from '@angular/core/testing';
import { NO_ERRORS_SCHEMA } from '@angular/core';
import { SharkValid, SharkValidForm, Common } from "@shark/shark-angularX";
import { RouterTestingModule } from '@angular/router/testing';
import { ProduceScheduleComponent } from './produce-schedule.component';
import { ProduceScheduleService } from './produce-schedule.service';
 
describe('#ProduceScheduleComponent', () => {
    let produceScheduleService;
    let fixture;
    let component;
    let getProceedingListSpy;
    let selectDom;
    let data = {
        code: 200,
        data: {
            pagination: {
                page: 1,
                size: 10,
                total: 354,
                totalPage: 36,
                offset: 0
            },
            result: [{}]
        }
    };
    beforeEach(() => {
        // 创建 ProduceScheduleService实例,并伪造了`getProceedingList()`方法
        const produceScheduleService = jasmine.createSpyObj('ProduceScheduleService', ['getProceedingList']);
        // 设置伪造的`getProceedingList()`方法的返回值
        getProceedingListSpy = produceScheduleService.getProceedingList.and.returnValue(new Promise<any>((resolve, reject) => { resolve(data) }));
        // 引入组件测试环境的依赖
        TestBed.configureTestingModule({
          // RouterTestingModule:建立测试需要的路由
            imports: [RouterTestingModule],
            declarations: [ProduceScheduleComponent, SharkValidForm, SharkValid],
            providers: [{ provide: ProduceScheduleService, useValue: produceScheduleService }, Common],
            // 对嵌套组件,可能包含更多组件
            //NO_ERRORS_SCHEM会要求 Angular 编译器忽略不认识的那些元素和属性
            schemas: [NO_ERRORS_SCHEMA]
        });
        fixture = TestBed.createComponent(ProduceScheduleComponent);
        component = fixture.componentInstance;
    });
    // 测试组件是否创建成成功
    it('should create the ProduceScheduleComponent', async(() => {
        expect(component).toBeTruthy();
    }));
    // 测试getProceedingList方法有没有被调用
    it('should call getProceedingList after component initialized', () => {
        fixture.detectChanges(); 
        // sync spy result shows getProceedingList immediately after init
        expect(getProceedingListSpy.calls.any()).toBe(true, 'getProceedingList called');
    });
});

例子2:下面是一个列表组件ProduceScheduleComponent(带输入的组件)

调用组件代码

<schedule-item [purchaseItem]="item"></schedule-item>
 

ScheduleItemComponent组件的测试代码

import { TestBed, async } from '@angular/core/testing';
import { NO_ERRORS_SCHEMA } from '@angular/core';
import { SharkToastrService, SharkModalService } from "@shark/shark-angularX";
import { RouterTestingModule } from '@angular/router/testing';
import { ScheduleItemComponent } from './schedule-item.component';
import { PurchaseStatePipe } from '../purchase-state.pipe'
import { SharedModule } from '../../../shared/shared.module'
 
describe('#ScheduleItemComponent', () => {
    let fixture;
    let component;
    let purchaseOrderEl;
    let purchaseItem = {
        purchaseOrder: "1375870000011112-20171024-32",
        allowModify: true,
        isVersion1_0: 0,
        purchaseOrderType: 2,
        purchaseOrderSaleModel: 1,
    }
    beforeEach(() => {
        TestBed.configureTestingModule({
            imports: [RouterTestingModule, SharedModule],
            declarations: [ScheduleItemComponent, PurchaseStatePipe],
            providers: [SharkToastrService, SharkModalService],
            // test will not load sub components
            schemas: [NO_ERRORS_SCHEMA]
        });
        fixture = TestBed.createComponent(ScheduleItemComponent);
        component = fixture.componentInstance;
        // 给组件传入purchaseItem数据
        component.purchaseItem = purchaseItem;
        fixture.detectChanges();
 
    });
 
    // 测试输入数据中采购单号在页面显示的正确性
    it('should display same purchaseOrder as purchaseItem.purchaseOrder ', () => {
        // 查找显示采购单号的标签元素
        purchaseOrderEl = fixture.nativeElement.querySelectorAll('b')[0];
        const purchaseOrder = purchaseItem.purchaseOrder;
        expect(purchaseOrderEl.textContent).toContain(purchaseOrder);
    });
});
 
  1. 组件Dom测试

测试组件是否能正常渲染出来、响应用户的输入和查询或与它的父组件和子组件相集成

例子:略

二、Directive

Directive作为宿主元素的属性来被使用的, 需要创建宿主元素来对指令的行为进行测试

例子:ShowAndHideListDirective的功能是控制table行数展示,并有展开、收起功能

import { Directive, ElementRef, HostListener, Input } from '@angular/core'
 
@Directive({
    selector: '[showAndHideList]'
})
export class ShowAndHideListDirective {
    private el: HTMLElement;
    @Input('showAndHideList') initNum: number;
 
    constructor(el: ElementRef) {
        this.el = el.nativeElement;
        this.el.style.backgroundColor = '#f4f4f4';
    }
    @HostListener('click') onClick() {
        var isHide = false;
        var groups = this.el.parentElement.parentElement.getElementsByTagName('tr');
        for (var i = this.initNum; i < groups.length; i++) {
            var item = groups[i];
            if (item.id == 'showAndHide') {
                break;
            }
            if (item.classList.contains('hide')) {
                item.classList.remove('hide');
                isHide = true;
            } else {
                item.classList.add('hide');
                isHide = false;
            }
        }
        if (isHide) {
            this.el.innerHTML = "收起商品<i class = 'icon-up'></i>"
        } else {
            this.el.innerHTML = "全部商品<i class = 'icon-down'></i>"
        }
    }
}

ShowAndHideListDirective指令的测试代码

import { Component, OnInit } from '@angular/core'
import { TestBed } from '@angular/core/testing';
import { ShowAndHideListDirective } from './showAndHideList.directive'
 
@Component({
    template: `
    <div class="table-wrap margin-b-4x">
      <table class="table table-full text-center">
          <thead>
              <tr>
                  <th>严选SKU ID</th>
                  <th>商品名称</th>
                  <th>规格</th>
              </tr>
          </thead>
          <tbody class="text-center">
              <tr *ngFor="let item of skuItems;index as i " [ngClass]="{'hide':i > initNum-1}">
                  <td>{{item.skuId}}</td>
                  <td>{{item.itemName}}</td>
                  <td>{{item.specValueDesc}}</td>
              </tr>
              <tr [ngClass]="{'hide': initNum >= skuItems.length}" id="showAndHide">
                  <td [showAndHideList]="initNum" [attr.colspan]="3" class="text-center text-gold text-cursor-pointer ">全部商品
                      <i class="icon-down"></i>
                  </td>
              </tr>
          </tbody>
      </table>
    </div>`,
    styleUrls: ['./test.component.scss']
})
class TestComponent {
    initNum: any = 3;
    skuItems: any = [{
        itemId: 10843001,
        itemName: "简约收纳盒",
        specValueDesc: "尺寸:大",
        skuId: 10924002
    }, {
        itemId: 10843001,
        itemName: "简约收纳盒",
        specValueDesc: "尺寸:中",
        skuId: 10924003
    }, {
        itemId: 10843001,
        itemName: "简约收纳盒",
        specValueDesc: "尺寸:小",
        skuId: 10924004
    },
    {
        itemId: 10843001,
        itemName: "女士水桶包",
        specValueDesc: "颜色:红",
        skuId: 10924005
    },
    {
        itemId: 10843001,
        itemName: "女士水桶包",
        specValueDesc: "颜色:黑",
        skuId: 10924006
    },
    {
        itemId: 10843001,
        itemName: "女士水桶包",
        specValueDesc: "颜色:白",
        skuId: 10924007
    },
    {
        itemId: 10843001,
        itemName: "男士T恤",
        specValueDesc: "尺寸:M",
        skuId: 10924008
    },
    {
        itemId: 10843001,
        itemName: "男士T恤",
        specValueDesc: "尺寸:L",
        skuId: 10924009
    }
    ];
}
describe('ShowAndHideListDirective', () => {
    let fixture;
    beforeEach(() => {
        fixture = TestBed.configureTestingModule({
            declarations: [ShowAndHideListDirective, TestComponent]
        }).createComponent(TestComponent);
    });
    // 测试表格原本的行数
    it('should have 10 <tr>', () => {
        fixture.detectChanges();
        const tr: any = fixture.nativeElement.querySelectorAll('tr');
        expect(tr.length).toBe(10);
    });
    // 测试表格隐藏的行数
    it('should have 5 <tr> with hide', () => {
        fixture.detectChanges();
        const tr: any = fixture.nativeElement.querySelectorAll('.hide');
        expect(tr.length).toBe(5);
    });
    // 测试点击展开全部按钮后隐藏的行数
    it('should have 0 <tr> with hide', () => {
        const display = fixture.nativeElement.querySelector('#showAndHide');
        display.click();
        const tr: any = fixture.nativeElement.querySelectorAll('.hide');
        expect(tr.length).toBe(0);
    });
 
});
 

三、Service(非http服务)

service的测试 非http服务基本上不需要依赖Angular的测试工具集.按普通类对待就好,我们以下面的例子说明

eg .目录结构如下

|-- demo
    |-- master.service.js
    |-- master.service.spec.js
    |-- value.service.js
    |-- value.service.spec.ts

valueService 是一个简单的Service。包含有若干方法

// demo/value.service.js
 
import { Injectable } from '@angular/core'
import { Observable } from 'rxjs'
 
@Injectable()
export class ValueService {
    constructor() { }
 
    getValue() {
        return { data: 123 }
    }
 
    getValue1() {
        return Observable.of({ data: 456 })
    }
 
    getValue2() {
        return new Promise((resolve, reject) => {
            resolve({ data: 789 })
        })
    }
}
 

对ValueService的测试如下:你会发现,和我们平时写代码是一样的,只不过多了一个断言判断

import { ValueService } from './value.service'
 
describe('MasterService', () => {
    let service: ValueService;
 
    beforeEach(() => {
        service = new ValueService();
    })
 
    it('#getValue should return real value', () => {
        expect(service.getValue()).toEqual({ data: 123 })
    })
 
    it('#getValue1 should return value from observable', async () => {
        service.getValue1().subscribe(value => {
            expect(value).toEqual({ data: 456 })
        })
    })
 
    it('#getValue2 should return value from promise', async () => {
        service.getValue2().then(value => {
            expect(value).toEqual({ data: 789 })
        })
    })
})

MasterService 依赖了ValueService

// demo/master.service.js
 
import { Injectable } from '@angular/core';
import { ValueService } from './value.service';
 
@Injectable()
export class MasterService {
    constructor(private valueService: ValueService) {
 
    }
    getValue() {
        return this.valueService.getValue();
    }
}
 

对于有依赖的服务。有很多种测试方案:

  1. 如果依赖的服务相对简单,而且可靠,这时候可以直接引入真实依赖。做法和产品代码环境一样:
// demo/master.service.spec.js
 
import { ValueService } from './value.service'
import { MasterService } from './demo'
 
describe('MasterService real', () => {
    let service: ValueService;
    let masterServie: MasterService;
 
    beforeEach(() => {
        service = new ValueService();
        masterServie = new MasterService(service);
    })
 
    it('#getValue should return real value', () => {
        expect(masterServie.getValue()).toEqual({ data: 123 })
    })
})
 
  1. Spy:利用spyObj来替换真实的依赖,并借助testBed创建类并注入服务
 
import { ValueService } from './value.service'
import { MasterService } from './master.service'
import { TestBed } from '@angular/core/testing';
 
describe('', () => {
    let masterService: MasterService;
    let valueServiceSpy: jasmine.SpyObj<ValueService>;
    // 每个it测试前都会运行的前置条件
    beforeEach(() => {
        // 创建一个spy对象
        const spy = jasmine.createSpyObj('ValueService', ['getValue']);
        // 在TestBed提供并注入服务
        TestBed.configureTestingModule({
            providers: [
                MasterService,
                { provide: ValueService, useValue: spy }
            ]
        });
        // 获取服务
        masterService = TestBed.get(MasterService);
        valueServiceSpy = TestBed.get(ValueService);
    });
    it('#getValue should return stubbed value from a spy', () => {
        const stubValue = { data: 123 };
        valueServiceSpy.getValue.and.returnValue(stubValue);
        // 数据 断言
        expect(masterService.getValue())
            .toBe(stubValue, 'service returned stub value');
        // 调用次数 断言
        expect(valueServiceSpy.getValue.calls.count())
            .toBe(1, 'spy method was called once');
        // 最近一次返回的数据 断言
        expect(valueServiceSpy.getValue.calls.mostRecent().returnValue)
            .toBe(stubValue);
    });
})
 

如果我们要测的服务含有http请求,一般是采用mock的方式,考虑到我们项目中的的实际情况,这里的测试验证点在于:
  1、是否发出了请求(代码是否执行)
  2、是否发出了预期的请求(请求路径是否正确、请求方法是否正确)
  3、是否发出了非预期的请求(有没有胡乱发送请求)
  4、对返回code的处理是否符合预期(code = 200正确预期是否成立 ,code = 400,错误的预期是否成立)
eg.
以大制造家中的supplier-info.service.ts为例

import { Injectable } from '@angular/core'
import { Ajax } from '@shark/shark-angularX'
import { Observable } from 'rxjs'
 
@Injectable()
export class SupplierInfo {
    private getSupplierInfoUrl = '/login/getSupplierInfo.json' 
    infoData: any = void 0
    constructor(
        private ajax: Ajax
    ) {
    }
 
    getSupplierInfo(obj: Object = {}) {
        if (this.infoData) {
            return Observable.of(this.infoData);
        }
        else {
            return Observable.fromPromise<any>(
                this.ajax.get(this.getSupplierInfoUrl, obj).then(data => {
                    this.infoData = data
                    return this.infoData
                })
            )
        }
    }
}

其测试用例的写法为:具体见注释

import { NO_ERRORS_SCHEMA } from '@angular/core';
import { Common, Ajax, Cookie } from '@shark/shark-angularX'
import { TestBed, tick } from '@angular/core/testing';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { HttpClient, HttpErrorResponse } from '@angular/common/http';
import { SupplierInfo } from './supplier-info.service';
 
describe('#SupplierInfo', () => {
    let httpClient: HttpClient;
    let httpTestingController: HttpTestingController;
    let supplierInfo: SupplierInfo;
    let ajax: Ajax;
    beforeEach(() => {
        TestBed.configureTestingModule({
            // http test 依赖 HttpClientTestingModule
            imports: [HttpClientTestingModule],
            // SupplierInfo 依赖 Ajax,而Ajax依赖Common, Cookie,这些都必须在providers里注明
            providers: [Ajax, Common, Cookie, SupplierInfo],
            schemas: [NO_ERRORS_SCHEMA]
        });
        // 各服务获取
        httpClient = TestBed.get(HttpClient);
        httpTestingController = TestBed.get(HttpTestingController);
        ajax = TestBed.get(Ajax);
        supplierInfo = TestBed.get(SupplierInfo);
        // 成功数据 
        this.expectedSupplierInfoSuccess = {
            code: 200,
            data: {
 
            }
        };
        // 失败数据 
        this.expectedSupplierInfoFail = {
            code: 400,
            errorCode: 'xxxx'
        }
    });
 
    afterEach(() => {
        // 验证没有发起过预期之外的请求
        httpTestingController.verify();
    });
 
    it('SupplierInfo service should be defined',
        () => {
            expect(supplierInfo).toBeDefined;
        }
    )
 
    it('infoData should be undefinded before the first call for getSupplierInfo',
        () => {
            expect(supplierInfo.infoData).toBeUndefined;
        }
    )
 
    it('infoData should be the supplierInfo after the first call for getSupplierInfo',
        () => {
            supplierInfo.getSupplierInfo();
            const req1 = httpTestingController.expectOne('/login/getSupplierInfo.json');
            req1.flush(this.expectedSupplierInfoSuccess);
            supplierInfo.getSupplierInfo();
            const req2 = httpTestingController.expectOne('/login/getSupplierInfo.json');
            req2.flush(this.expectedSupplierInfoSuccess);
            expect(supplierInfo.infoData).toBeDefined;
        }
    )
 
    it('getSupplierInfo should return value from observable when the response is success',
        () => {
            // 操作
            supplierInfo.getSupplierInfo().subscribe(value => {
                expect(value).toEqual(this.expectedSupplierInfoSuccess, 'should return expected expectedSupplierInfoSuccess'),
                    data => fail('should have successed with the data')
            });
            // 请求路径验证
            const req = httpTestingController.expectOne('/login/getSupplierInfo.json');
            // 请求method验证
            expect(req.request.method).toEqual('GET', 'the request method shoud be GET');
            // 指定返回数据 resolve Observable 
            req.flush(this.expectedSupplierInfoSuccess);
        });
 
    it('getSupplierInfo should return value from observable when the response is fail',
        () => {
            // 操作
            supplierInfo.getSupplierInfo().subscribe(
                data => fail('should have failed with the errorCode'),
                value => {
                    expect(value).toEqual(this.expectedSupplierInfoFail, 'should return expected expectedSupplierInfoFail')
                });
            // 请求路径验证
            const req = httpTestingController.expectOne('/login/getSupplierInfo.json');
            // 请求method验证
            expect(req.request.method).toEqual('GET', 'the request method shoud be GET');
            // 指定返回数据 resolve Observable 
            req.flush(this.expectedSupplierInfoFail);
        });
});
 
  • pipe

pipe 除了 @Pipe元数据和一个接口基本上不依赖angular,所以它的测试很简单

eg. 以一个大制造家中的OrderBySkuId管道为例:

import { Pipe, PipeTransform } from '@angular/core';
 
/*
 * 按skuid排序 
*/
@Pipe({ name: 'orderBySkuId' })
export class OrderBySkuId implements PipeTransform {
    constructor(
    ) {
    }
    transform(list = []): any {
        if (list && list.length > 0) {
            return list.sort((a, b) => a.skuId - b.skuId);
        } else {
            return []
        }
    }
}
 

测试代码只需对其transform调用并断言即可:

import { OrderBySkuId } from './order-by-skuid.pipe';
import { each } from 'fpb';
 
describe('OrderBySkuIdPipe', () => {
    const orderBySkuIdPipe = new OrderBySkuId();
    const skuList = [{
        skuId: 3
    }, {
        skuId: 4
    }, {
        skuId: 1
    }, {
        skuId: 2
    }];
 
    const expectedData = [{
        skuId: 1
    }, {
        skuId: 2
    }, {
        skuId: 3
    }, {
        skuId: 4
    }];
 
    const expectedToEqualEmptyArr = each((v) => {
        expect(orderBySkuIdPipe.transform(v)).toEqual([]);
    })
    it('transforms null、 undefiend、""、[] to []', () => {
        expectedToEqualEmptyArr([null, undefined, '', []])
    });
    it('transforms list orderBy it\'s skuid property', () => {
        expect(orderBySkuIdPipe.transform(skuList)).toEqual(expectedData);
    });
})
 

常用测试技巧罗列:可参见 https://angular.cn/guide/testing


  1. 改写组件provider
  2. Dom测试封装(见angular测试指导 page类)
  3. spy的使用
  4. jasmine-marbles的使用

Package Sidebar

Install

npm i shark-test

Weekly Downloads

3

Version

1.0.4

License

none

Unpacked Size

126 kB

Total Files

65

Last publish

Collaborators

  • bobojiayou
  • jihanting