Angualr單元測試

Angualr單元測試

Angular自己的單元測試工具:Karma + Jasmine

  • Karma:是自動化測試管理工具,可以監(jiān)控文件,喚起關(guān)閉瀏覽器自動執(zhí)行測試。
  • Jasmine:用來編寫JavaScript測試的框架。

概念

Test Suite
  • 作用:將若干測試用例集合在一個分類下就叫測試套件
  • describe全局函數(shù)來表示,
    1. 它的第一個字符串參數(shù),用來表示Suite的名稱或標(biāo)題
    2. 第二個方法參數(shù)就是實現(xiàn)Suite代碼了
describe('test suite name', () => {
});
Specs
  • 作用:一個Specs相當(dāng)于一個測試用例
  • it全局函數(shù)來表示,和describe類似,字符串和方法兩個參數(shù)。

每個測試用例包括多個exception來測試需要測試的代碼,只要任何一個斷言的結(jié)果為false就表示該測試用例為失敗狀態(tài)。

Expectations

斷言,使用expect全局函數(shù)來表示,只接受一個代表要測試的實際值,并且需要與Matcher代表期望值

常用方法

Matches

斷言匹配操作,在實際值與期望值之間進行比較,并將結(jié)果通知Jasmine,最終Jasmine會判斷此用例成功還是失敗。

常用Matchers

  • toBe(): === 基本類型判斷
  • toNotBe(): !==
  • toBeDefined():!== undefined
  • toBeUndefined(): === undefined
  • toBeNull(): === null
  • toBeTruthy(): !!obj 判斷是否能轉(zhuǎn)換成bool型,判斷是否是true
  • toBeFalsy(): !obj
  • toBeLessThan(): <
  • toBeGreaterThan(): >
  • toEqual(): 有兩種用法,1. 對于基本的類型,相當(dāng)于toBe(); 2. 還可以用來判斷對象;
  • toNotEqual():
  • toContain() indexOf 判斷集合是否包含(可以是普通類型,可以是對象)
  • toHaveBeenCalled(): 檢查function是否被調(diào)用過
  • toHaveBeenCalledWith(): 檢查傳入?yún)?shù)是否被作為參數(shù)調(diào)用過
  • toMatch(): new RegExp().text() 使用正則表達式判斷
  • ToNotMatch(): 等同!new RegExp().text()
  • toThrow(): 檢查function是否會拋出一個錯誤
  • toBeCloseTo: 判斷數(shù)字

這些API之前可以用not來表示負(fù)值的判斷

Setup與Teardown

將重復(fù)的setup與teardown代碼,放在與之相對應(yīng)的beforEach與afterEach全局函數(shù)里面

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可以相互嵌套

跳過測試代碼

xdescribe xit

配合Angualr工具集

Spy

為了測試自定義事件是否正常被調(diào)用,是非常重要的。Spy可以用來監(jiān)測函數(shù)是否被調(diào)用,這簡直就是我們的好伙伴。

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

    beforeEach(() => {
        TestBed.configureTestingModule({
            declarations: [TestComponent]
        });
        fixture = TestBed.createComponent(TestComponent);
        context = fixture.componentInstance;
        // 監(jiān)聽onSelected方法
        spyOn(context, 'onSelected');
        fixture.detectChanges();
    });

    it('should be called [selected] event.', () => {
        // 觸發(fā)selected操作

        // 斷言是否被調(diào)用過
        expect(context.onSelected).toHaveBeenCalled();
    });
});

Spy用來追蹤函數(shù)的調(diào)用歷史信息(是否被調(diào)用,調(diào)用參數(shù)列表,被請求次數(shù)等)。Spy僅存在于定義它的describe和it方法塊中,并且每次在測試用例執(zhí)行完后被銷毀

spy常用
  1. and.callThrough()在使用spy的同時也會執(zhí)行實際的代碼。

  2. and.returnValue()由于spy是模擬函數(shù)的調(diào)用,因此我們也可以強制指定函數(shù)的返回值。

  3. and.callFake()和returnValue相似,callFake則更進一步,直接通過指定一個假的自定義函數(shù)來執(zhí)行。比returnValue更靈活,我們可以任意捏造一個函數(shù)來達到我們的測試要求

     spyOn(foo, "getBar").and.callFake(function() {
              return 1001;
     });
    
  4. and.thorwErrow模擬異常的拋出;

  5. and.stub重置spy

其他追蹤屬性

calls: 對于被spy的函數(shù)的調(diào)用,都可以在calls屬性中跟蹤

  • .calls.any():被Spy的函數(shù)一旦被調(diào)用過,則返回true,否則為false
  • .calls.count():返回被Spy的函數(shù)的被調(diào)用次數(shù)
  • .calls.argsFor(index):返回被spy的函數(shù)的調(diào)用參數(shù),以index來指定參數(shù)
  • .calls.allArgs:返回被spy的函數(shù)的所有調(diào)用參數(shù);
  • .callls.all(): 返回calls的上下文,將返回當(dāng)前calls的整個實例數(shù)據(jù);
  • .calls.mostRecent():返回calls中追蹤的最近一次的請求數(shù)據(jù);
  • .calls.first():返回calls中追蹤的第一次請求的數(shù)據(jù);
  • .object: 當(dāng)調(diào)用all(),mostRecent(),first()方法時,返回對象的object屬性返回的是當(dāng)前上下文對象
  • .calls.reset(): 重置spy的所有追蹤數(shù)據(jù);
createSpy
createSpyObj

異步支持

首先,這里的異步是指帶有Observable或promise的異步行為,因此對于組件在調(diào)用某個Service來異步獲取數(shù)據(jù)的時候測試狀態(tài)

async

async無任何參數(shù)與返回值,所有包裹在代碼塊里的測試代碼,可以通過調(diào)用whenStable()讓所有異步行為都完成后再進行回調(diào):最后,再進行斷言操作。

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

將回調(diào)換成tick()

it('should be get user list (async)', fakeAsync(() => {
    // call component.query();
    tick();
    fixture.detectChanges();
    expect(true).toBe(true);
}));
Jasmine自帶異步
  1. 前面的異步是指Observable或Promise的異步行為
  2. setTimeout或者可能是需要外部訂閱結(jié)果以后才能觸發(fā)done()方法
it('async demo', (done: () => void) => {
    context.show().subscribe(res => {
        expect(true).toBe(true);
        done();
    });
    el.querySelected('xxx').click();
});
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容