Angular单元测试框架里API toHaveBeenCalledTimes的工作原理

看这样一段代码:

 let spiedFirstFocusable = spyOn(
      keyboardFocusService,
      'findFirstFocusable'
    ).and.returnValue(el);
    fixture.detectChanges();

    expect(document.activeElement.id).toEqual('a');
    expect(spiedFirstFocusable).toHaveBeenCalledTimes(ELEMENT_FOCUSED_TIME);

spiedFirstFocusable是spyOn方法针对实例keyboardFocusService的findFirstFocusable方法进行监控后返回的句柄。借助该句柄,我们可以使用toHaveBeenCalledTimes方法,得到其在单元测试过程中实际调用的次数。

Angular单元测试框架里API toHaveBeenCalledTimes的工作原理_第1张图片

expect方法:基于传入的spec创建一个expectation. 在我们的例子里,传入的spec就是keyboardFocusService.findFirstFocusable被spy之后的版本:

Angular单元测试框架里API toHaveBeenCalledTimes的工作原理_第2张图片

Expectation通过工厂方法创建,该工厂方法接受两个参数,第一个参数为spied method handle:

Angular单元测试框架里API toHaveBeenCalledTimes的工作原理_第3张图片

第二个参数为单元测试代码运行的spec信息,即下图高亮代码:

Angular单元测试框架里API toHaveBeenCalledTimes的工作原理_第4张图片

Expectation工厂方法的实现细节,我们可以略过:

Angular单元测试框架里API toHaveBeenCalledTimes的工作原理_第5张图片

toHaveBeenCalledTimes的函数体是之前wrapSyncCompare包裹函数返回的一个闭包:

Angular单元测试框架里API toHaveBeenCalledTimes的工作原理_第6张图片

待compare的业务逻辑写在函数matcherFactory里:

Angular单元测试框架里API toHaveBeenCalledTimes的工作原理_第7张图片

Angular单元测试框架里API toHaveBeenCalledTimes的工作原理_第8张图片

以后我们可以直接在函数toHaveBeenCalledTimes里设置断点调试。

  1. 检查传入的actual是否是一个spied后的函数。
  2. 将检查结果设置成默认值false.
  3. 检查传入的期望调用次数的值的数据类型是否是Number

Angular单元测试框架里API toHaveBeenCalledTimes的工作原理_第9张图片

Spied版本的函数调用明细,存储在CallTracker的calls属性里:

Angular单元测试框架里API toHaveBeenCalledTimes的工作原理_第10张图片

这个数组里包含的监控到的方法调用信息有:

  1. 方法调用的输入参数
  2. 调用方法的实例对象
  3. 调用方法的返回参数

"get the number of invocations of this spy"的实现方法:calls.length

Angular单元测试框架里API toHaveBeenCalledTimes的工作原理_第11张图片

如果calls.length和传入的期望值expected相等,说明匹配成功,返回success结果:

Angular单元测试框架里API toHaveBeenCalledTimes的工作原理_第12张图片

更多Jerry的原创文章,尽在:"汪子熙":

你可能感兴趣的:(Angular单元测试框架里API toHaveBeenCalledTimes的工作原理)