Angualr单元测试
Angular自己的单元测试工具:Karma
+ Jasmine
- Karma:是自动化测试管理工具,可以监控文件,唤起关闭浏览器自动执行测试。
- Jasmine:用来编写JavaScript测试的框架。
概念
Test Suite
- 作用:将若干测试用例集合在一个分类下就叫测试套件
- 用
describe
全局函数来表示,- 它的第一个字符串参数,用来表示Suite的名称或标题
- 第二个方法参数就是实现Suite代码了
describe('test suite name', () => {
});
Specs
- 作用:一个Specs相当于一个测试用例
- 用
it
全局函数来表示,和describe类似,字符串和方法两个参数。
每个测试用例包括多个exception来测试需要测试的代码,只要任何一个断言的结果为false就表示该测试用例为失败状态。
Expectations
断言,使用expect全局函数来表示,只接受一个代表要测试的实际值,并且需要与Matcher代表期望值
常用方法
Matches
断言匹配操作,在实际值与期望值之间进行比较,并将结果通知Jasmine,最终Jasmine会判断此用例成功还是失败。
常用Matchers
- toBe(): === 基本类型判断
- toNotBe(): !==
- toBeDefined():!== undefined
- toBeUndefined(): === undefined
- toBeNull(): === null
- toBeTruthy(): !!obj 判断是否能转换成bool型,判断是否是true
- toBeFalsy(): !obj
- toBeLessThan(): <
- toBeGreaterThan(): >
- toEqual(): 有两种用法,1. 对于基本的类型,相当于toBe(); 2. 还可以用来判断对象;
- toNotEqual():
- toContain() indexOf 判断集合是否包含(可以是普通类型,可以是对象)
- toHaveBeenCalled(): 检查function是否被调用过
- toHaveBeenCalledWith(): 检查传入参数是否被作为参数调用过
- toMatch(): new RegExp().text() 使用正则表达式判断
- ToNotMatch(): 等同!new RegExp().text()
- toThrow(): 检查function是否会抛出一个错误
- toBeCloseTo: 判断数字
这些API之前可以用not
来表示负值的判断
Setup与Teardown
将重复的setup与teardown代码,放在与之相对应的beforEach与afterEach全局函数里面
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
为了测试自定义事件是否正常被调用,是非常重要的。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();
});
});
Spy用来追踪函数的调用历史信息(是否被调用,调用参数列表,被请求次数等)。Spy仅存在于定义它的describe和it方法块中,并且每次在测试用例执行完后被销毁
spy常用
and.callThrough()
在使用spy的同时也会执行实际的代码。and.returnValue()
由于spy是模拟函数的调用,因此我们也可以强制指定函数的返回值。-
and.callFake()
和returnValue相似,callFake则更进一步,直接通过指定一个假的自定义函数来执行。比returnValue更灵活,我们可以任意捏造一个函数来达到我们的测试要求spyOn(foo, "getBar").and.callFake(function() { return 1001; });
and.thorwErrow
模拟异常的抛出;and.stub
重置spy
其他追踪属性
calls: 对于被spy的函数的调用,都可以在calls属性中跟踪
。
-
.calls.any()
:被Spy的函数一旦被调用过,则返回true,否则为false -
.calls.count()
:返回被Spy的函数的被调用次数 -
.calls.argsFor(index)
:返回被spy的函数的调用参数,以index来指定参数 -
.calls.allArgs
:返回被spy的函数的所有调用参数; -
.callls.all()
: 返回calls的上下文,将返回当前calls的整个实例数据; -
.calls.mostRecent()
:返回calls中追踪的最近一次的请求数据; -
.calls.first()
:返回calls中追踪的第一次请求的数据; -
.object
: 当调用all(),mostRecent(),first()方法时,返回对象的object属性返回的是当前上下文对象 -
.calls.reset()
: 重置spy的所有追踪数据;
createSpy
createSpyObj
异步支持
首先,这里的异步是指带有Observable或promise的异步行为,因此对于组件在调用某个Service来异步获取数据的时候测试状态
async
async无任何参数与返回值,所有包裹在代码块里的测试代码,可以通过调用whenStable()让所有异步行为都完成后再进行回调:最后,再进行断言操作。
it('should be get user list (async)', async(() => {
// call component.query();
fixture.whenStable().then(() => {
fixture.detectChanges();
expect(true).toBe(true);
});
}));
fakeAsync
将回调换成tick()
it('should be get user list (async)', fakeAsync(() => {
// call component.query();
tick();
fixture.detectChanges();
expect(true).toBe(true);
}));
Jasmine自带异步
- 前面的异步是指Observable或Promise的异步行为
- setTimeout或者可能是需要外部订阅结果以后才能触发done()方法
it('async demo', (done: () => void) => {
context.show().subscribe(res => {
expect(true).toBe(true);
done();
});
el.querySelected('xxx').click();
});