ngMock
angular的單元測(cè)試是通過(guò)內(nèi)建的ngmock完成的
它主要由兩個(gè)函數(shù)
angular.mock.module------在單元測(cè)試中加載模塊
接受三種參數(shù):
字符串: 指定了需要加載的模塊轧房;
回調(diào)函數(shù):為了達(dá)到單元測(cè)試隔離的目的,需要?jiǎng)?chuàng)建臨時(shí)組件來(lái)代替實(shí)際組件,臨時(shí)組件需要容器,當(dāng)module使用回調(diào)函數(shù)的時(shí)候,會(huì)定義一個(gè)匿名模塊迷殿,回調(diào)函數(shù)中聲明的組件被注冊(cè)在匿名模塊中;
對(duì)象參數(shù):也會(huì)定義一個(gè)匿名模塊,這個(gè)對(duì)象參數(shù)里的每一對(duì)值將會(huì)成為一個(gè)value組件酸休;
回調(diào)函數(shù)和對(duì)象參數(shù)都會(huì)定義一個(gè)匿名模塊,并在匿名模塊中創(chuàng)建測(cè)試用的臨時(shí)組件祷杈。
我們已經(jīng)加載了模塊斑司,如何獲得模塊中組件的實(shí)例呢?
angular.mock.inject--------在單元測(cè)試中注入依賴(lài)組件
inject函數(shù)為每個(gè)測(cè)試用例創(chuàng)建并封裝了一個(gè)$injector但汞,注入測(cè)試所需要的組件實(shí)例宿刮,但是同名組件會(huì)覆蓋,利用這個(gè)特性來(lái)創(chuàng)建假組件
2.測(cè)試替身
作用:為被測(cè)單元提供輸入數(shù)據(jù)特占;記錄被測(cè)單元測(cè)輸出結(jié)果
分類(lèi):
● 測(cè)試啞元: 只是幫助測(cè)試項(xiàng)目編譯通過(guò)糙置,不在具體測(cè)試?yán)锩嫫鹑魏巫饔?br>
被測(cè)單元的函數(shù)可能會(huì)接受一些參數(shù),然后將傳入的參數(shù)對(duì)象存在實(shí)例變量里 供以后使用是目。有時(shí)候這些參數(shù)對(duì)象不會(huì)在當(dāng)前的單元測(cè)試過(guò)程中被使用谤饭,所以它們不會(huì)影響被測(cè)函數(shù)/方法的行為。 最簡(jiǎn)單的Dummy Object是null。
● 測(cè)試樁:代碼中不包含邏輯揉抵,作為替身只返回固定數(shù)據(jù)
● 測(cè)試間諜: 有時(shí)候函數(shù)并沒(méi)有返回值亡容,驗(yàn)證就需要記錄并保存所有對(duì)它的調(diào)用信息
● mock objects: 在spy的基礎(chǔ)上加入了驗(yàn)證的功能,測(cè)試用例本身不需要驗(yàn)證代碼
● fake objects: 創(chuàng)建一個(gè)內(nèi)存數(shù)據(jù)庫(kù)來(lái)取代一個(gè)真實(shí)的數(shù)據(jù)庫(kù)
2.1spyOn()
2.1.1 spyOn(foo, 'setBar') 創(chuàng)建spy替換實(shí)際已存在的函數(shù)
2.1.2 監(jiān)測(cè)函數(shù)的調(diào)用和參數(shù)的調(diào)用痕跡冤今;Spy的調(diào)用并不會(huì)影響真實(shí)的值
2.2 createSpy
2.2.1 whatAmI = jasmine.createSpy('whatAmI'); 如果只需要一個(gè)空函數(shù)闺兢,用它來(lái)創(chuàng)建一個(gè)全新的函數(shù),不用替換實(shí)際函數(shù)戏罢;
2.2.2 jasmine.createSpy可以創(chuàng)建一個(gè)“空白”的spy屋谭。該spy會(huì)像其他間諜一樣追蹤調(diào)用,函數(shù)等等龟糕,但是在其之后并不會(huì)有實(shí)際實(shí)現(xiàn)的返回值
2.3 createSpyObj
2.3.1 多重spies的模擬
2.2spy可以進(jìn)行的鏈?zhǔn)秸{(diào)用
2.2.1 and.callThrough 除了追蹤所有的調(diào)用之外桐磁,執(zhí)行實(shí)際函數(shù),更新被測(cè)單元的數(shù)據(jù)
2.2.2 and.returnValues 所有調(diào)用該spy的函數(shù)都將按順序返回一些特定的值,沒(méi)有返回值讲岁,返回undefined我擂;
函數(shù)遞歸
來(lái)個(gè)栗子:
2.2.3 and.returnValue
2.2.4 and.callFake 調(diào)用該spy的都將調(diào)用其提供的函數(shù),拿到函數(shù)提供的返回值
舉個(gè)栗子:
2.2.5 and.throwError 該spy的將以一個(gè)錯(cuò)誤的形式拋出特殊返回值
2.2.6 and.stub 返回之前保存的原始數(shù)據(jù)
其他被追蹤的屬性:
- .calls.any():一次都沒(méi)調(diào)用時(shí)返回false缓艳,一旦調(diào)用至少一次就返回true校摩;
- .calls.count():返回spy調(diào)用的次數(shù)
- .calls.argsFor(index):返回第index+1次調(diào)用時(shí)傳遞的參數(shù),index從0開(kāi)始阶淘;
- .calls.allArgs():以數(shù)組的形式返回調(diào)用時(shí)傳遞的所有參數(shù)衙吩;
- .calls.all():以對(duì)象形式返回上下文(this),以及所有傳遞的參數(shù)溪窒;
- .calls.mostRecent():以對(duì)象形式返回最近一次調(diào)用的上下文(this)分井,以及傳遞的參數(shù);
- .calls.first():以對(duì)象形式返回第一次調(diào)用的上下文(this)霉猛,以及傳遞的參數(shù)尺锚;(當(dāng)檢查.calls.all(),.calls.mostRecent()惜浅,.calls.first()返回的對(duì)象時(shí)瘫辩,.object屬性指向的是調(diào)用該spy的this對(duì)象)
- .calls.reset():清空spy的所有追蹤。
3.describe,it,matchers,beforeEach()坛悉,afterEach()伐厌,beforeAll(),afterAll()
3.1在describe函數(shù)中重聲明的變量在其下的it函數(shù)體都是可用的
3.2任何Matcher都能通過(guò)在expect調(diào)用Matcher前加上not來(lái)實(shí)現(xiàn)一個(gè)否定的斷言
3.3Matchers很豐富裸影,也可以自定義
3.4beforeEach()函數(shù)在每一個(gè)spec調(diào)用時(shí)調(diào)用挣轨,先進(jìn)行初始化操作,而afterEach()則是在每一個(gè)spec調(diào)用之后調(diào)用
3.5beforeAll()函數(shù)在所有spec執(zhí)行前只調(diào)用一次轩猩,afterAll()則是在所有spec結(jié)束后調(diào)用一次
舉兩個(gè)栗子:
describe("A spec using beforeEach and afterEach", function () {
var foo = 0;
beforeEach(function () {
foo += 1;
});
afterEach(function () {
foo = 0;
});
it("is just a function, so it can contain any code", function () {
expect(foo).toEqual(1);
});
it("can have more than one expectation", function () {
expect(foo).toEqual(1);
expect(true).toEqual(true);
});
});
describe("A spec using beforeAll and afterAll", function () {
var foo;
beforeAll(function () {
foo = 1;
});
afterAll(function () {
foo = 0;
});
it("sets the initial value of foo before specs run", function () {
expect(foo).toEqual(1);
foo += 1;
});
it("does not reset foo between specs", function () {
expect(foo).toEqual(2);
});
});
● Jasmine會(huì)先執(zhí)行describe塊的代碼卷扮,然后再執(zhí)行beforeAll荡澎、beforeEach和it函數(shù)
● beforeAll先執(zhí)行一次
● 執(zhí)行一個(gè)it前,內(nèi)層如果有beforeAll晤锹。 執(zhí)行順序:
inner beforeAll
outer beforeEach
inner beforeEach
it用例執(zhí)行
inner afterEach
outer afterEach
inner afterAll
禁用或掛起測(cè)試:加x摩幔,不寫(xiě)函數(shù)體,在函數(shù)體內(nèi)使用pending()
4.async(() => {})
5.(() => {})
為什么需要一個(gè)同步的環(huán)境和一個(gè)異步的環(huán)境