Angular单元测试系列-怎样运用Jasmine举行Angular单元测试

以下是我假定那些少少或压根没写单元测试的人预备的,因而,会白话诠释诸多观点性问题,同时会连系 Jasmine 与之对应的要领举行解说。

一、观点

Test Suite

测试套件,哪怕一个简朴的类,也会有多少的测试用例,因而将这些测试用例集合在一个分类下就叫Test Suite

而在 Jasmine 就是运用 describe 全局函数来示意,它的第一个字符串参数用来示意Suite的称号或题目,第二个要领参数就是完成Suite代码了。

describe('test suite name', () => {
});

Specs

一个Specs相当于一个测试用例,也就是我们完成测试详细代码体。

Jasmine 就是运用 it 全局函数来示意,和 describe 相似,字符串和要领两个参数。

而每一个 Spec 内包含多个 expectation 来测试须要测试的代码,只需任何一个 expectation 效果为 false 就示意该测试用例为失利状况。

describe('demo test', () => {
    const VALUE = true;
    it('should be true', () => {
        expect(VALUE).toBe(VALUE);
    })
});

Expectations

断言,运用 expect 全局函数来示意,只吸收一个代表要测试的现实值,而且须要与 Matcher 代表期望值

二、常常使用要领

Matchers

断言婚配操纵,在现实值与期望值之间举行比较,并将效果关照Jasmine,终究Jasmine会推断此 Spec 胜利照样失利。

Jasmine 供应非常丰富的API,一些常常使用的Matchers:

  • toBe() 同等 ===
  • toNotBe() 同等 !==
  • toBeDefined() 同等 !== undefined
  • toBeUndefined() 同等 === undefined
  • toBeNull() 同等 === null
  • toBeTruthy() 同等 !!obj
  • toBeFalsy() 同等 !obj
  • toBeLessThan() 同等 <
  • toBeGreaterThan() 同等 >
  • toEqual() 相当于 ==
  • toNotEqual() 相当于 !=
  • toContain() 相当于 indexOf
  • toBeCloseTo() 数值比较时定义精度,先四舍五入后再比较。
  • toHaveBeenCalled() 搜检function是不是被挪用过
  • toHaveBeenCalledWith() 搜检传入参数是不是被作为参数挪用过
  • toMatch() 同等 new RegExp().test()
  • toNotMatch() 同等 !new RegExp().test()
  • toThrow() 搜检function是不是会抛出一个毛病

而这些API之前用 not 来示意负值的推断。

expect(true).not.toBe(false);

这些Matchers险些能够满足我们一样平常需求,固然你也能够定制本身的Matcher来完成特别需求。

Setup 与 Teardown

一份干将的测试代码很主要,因而我们能够将这些反复的 setup 与 teardown 代码,放在与之相对应的 beforeEachafterEach 全局函数内里。

beforeEach 示意每一个 Spec 实行之前,反之。

describe('demo test', () => {
    let val: number = 0;
    beforeEach(() => {
        val = 1;
    });
    it('should be true', () => {
        expect(val).toBe(1);
    });
    it('should be false', () => {
        expect(val).not.toBe(0);
    });
});

数据同享

犹如上面示例中,我们能够在每一个测试文件开首、describe 来定义响应的变量,如许每一个 it 内部能够同享它们。

固然,每一个 Spec 的实行周时期也会伴随着一个空的 this 对象,直至 Spec 实行完毕后被清空,应用 this 也能够做数据同享。

嵌套代码

有时刻当我们对某个组件举行测试时,而这个组件会有差别状况来展现差别的效果,这个时刻假如只用一个 describe 会显得不过文雅。

因而,嵌套 describe,会让测试代码、测试报告看起来更美丽。

describe('AppComponent', () => {
    describe('Show User', () => {
        it('should be show panel.', () => {});
        it('should be show avatar.', () => {});
    });
    describe('Hidden User', () => { 
        it('should be hidden panel.', () => {});
    });
});

跳过测试代码块

需求老是三心二意的,但十分困难写好的测试代码,岂非要删除吗?非也……

Suites 和 Specs 离别能够用 xdescribexit 全局函数来跳过这些测试代码块。

三、合营Angular东西集

Spy

Angular的自定义事宜实在太广泛了,但为了测试这些自定义事宜,因而监控事宜是不是正常被挪用是非常主要。幸亏,Spy 能够用于监测函数是不是被挪用,这简直就是我们的好同伴。

以下示例临时不必剖析,临时体验一下:

describe('AppComponent', () => {
    let fixture: ComponentFixture<TestComponent>;
    let context: TestComponent;

    beforeEach(() => {
        TestBed.configureTestingModule({
            declarations: [TestComponent]
        });
        fixture = TestBed.createComponent(TestComponent);
        context = fixture.componentInstance;
        // 监听onSelected要领
        spyOn(context, 'onSelected');
        fixture.detectChanges();
    });

    it('should be called [selected] event.', () => {
        // 触发selected操纵

        // 断言是不是被挪用过
        expect(context.onSelected).toHaveBeenCalled();
    });
});

异步支撑

起首,这里的异步是指带有 Observable 或 Promise 的异步行动,因而关于组件在挪用某个 Service 来异步猎取数据时的测试状况。

假定我们的待测试组件代码:

export class AppComponent {
  constructor(private _user: UserService) {}

  query() {
    this._user.quer().subscribe(() => {});
  }
}

async

async 无任何参数与返回值,一切包裹代码块里的测试代码,能够经由过程挪用 whenStable()一切待处理异步行动都完成后再举行回调;末了,再举行断言操纵。

it('should be get user list (async)', async(() => {
    // call component.query();
    fixture.whenStable().then(() => {
        fixture.detectChanges();
        expect(true).toBe(true);
    });
}));

fakeAsync

假如说 async 还须要回调才举行断点让你受不了的话,那末 fakeAsync 能够处理这一点。

it('should be get user list (async)', fakeAsync(() => {
    // call component.query();
    tick();
    fixture.detectChanges();
    expect(true).toBe(true);
}));

这里只是将回调换成 tick(),怎样,是不是是很酷。

Jasmine自带异步

如前面所说的异步是指带有 Observable 或 Promise 的异步行动,而有时刻我们有些东西是依靠 setTimeout 或许多是须要外部定阅效果今后才触发时怎么办呢?

能够运用 done() 要领。

it('async demo', (done: () => void) => {
    context.show().subscribe(res => {
        expect(true).toBe(true);
        done();
    });
    el.querySelected('xxx').click();
});

四、结论

本章险些一切的内容在Angular单元测试常常运用到的东西;特别是异步部份,三种差别异步体式格局并不是共存的,而是须要依据详细营业而采纳。不然,你会发明真TM难写单元测试。毕竟这是一个异步的天下。

自此,我们算是为Angular写单元测试打下了基本。后续,将不会再对这类基本举行诠释。

那末下一篇,我们将引见Component、Directive、Pipe 以及Service单元测试

happy coding!

    原文作者:cipchk
    原文地址: https://segmentfault.com/a/1190000009737204
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞