Angular学习笔记70:Angular项目的单元测试 -- 对组件进行测试

2023-11-15

对组件进行测试

对组件绑定的测试

例如在一个组件中,一个组件中模版里有一个标题的是

<h2 class='title'>{{title}}</h2>

组件的类文件中对应绑定了一个类文件中的属性,

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lSHcJkd6-1571041448340)(evernotecid://621D2FF6-4E72-4E02-9043-55F31F42819B/appyinxiangcom/22553815/ENResource/p209)]

  • 测试这个绑定的数据
it('should render title in a h2 tag ', () => {
    const fixtureEle = TestBed.createComponent(EnvNewComponent);
    fixtureEle.detectChanges();
    const compiled = fixtureEle.nativeElement;
    expect(compiled.querySelector('.title').textContent).toContain(component.title);
 expect(compiled.querySelector('h2').textContent).toContain(component.title);
  });

大体思路:

1. TestBed创建这个组件

通过 TestBed.createComponent() 方法创建出了当前的组件

2. 执行数据绑定

通过调用 fixture.detectChanges() 来要求 TestBed 执行数据绑定,才能获取到相应是数据绑定。

3. 查找元素

compiled.querySelector()是用来查找页面中的元素,可以根据标签、class属性值、等。

4. 断言判断

expect(compiled.querySelector(‘h2’).textContent).toContain(component.title);
查找出来的文字内容和组件中的属性进行比较是否一致。

需要注意的是TestBed.createComponent() 方法不会绑定数据,只有调用了detectChanges()才会进行数据绑定

查询具有某个属性的一系列元素使用

compiled.querySelectorAll()

自动检测变更

在测试文件中,经常需要调用 detectChanges() ,这样有时会出现遗漏或者书写繁琐的问题,现在可以让Angular 测试环境自动运行变更检测。在这里可以使用 ComponentFixtureAutoDetect 服务提供商来配置 TestBed 就可以做到这一点

TestBed.configureTestingModule({
      imports: [
        NgZorroAntdModule,
        TableModule,
        RouterTestingModule,
        SearchTableModule,
        HttpClientTestingModule,
        TranslateModule.forRoot()],
      declarations: [EnvNewComponent, BreadcrumbStubComponent],
      providers: [
        TranslateService,
        {provide: ComponentFixtureAutoDetect, useValue: true}
      ],
      schemas: [NO_ERRORS_SCHEMA]
    })
  • 自动检测变更的局限性

ComponentFixtureAutoDetect 也是有一定局限性的,在测试环境中改变了原有需要绑定的值时,自动检测变更是检测不出来的,只有显性调用 detectChanges() 才会检测出变化。
即:

it('should render title in a h2 tag ', () => {
    const fixtureEle = TestBed.createComponent(EnvNewComponent);
    // fixtureEle.detectChanges();
    const compiled = fixtureEle.nativeElement;
    component.title = 'Test Demo';
  expect(compiled.querySelector('.title').textContent).toContain('NotEnvsHost.notEnvsHost');
   expect(compiled.querySelector('h2').textContent).toContain(component.title);
  });

上述代码中 component.title = ‘Test Demo’; 这个变更,自动检测变更是检测不出来的。

带有外部文件的组件

通常大部分的组件都是将模版、样式文件分开放在不同的文件中的,就像这样:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pHPdtD2u-1571041448341)(evernotecid://621D2FF6-4E72-4E02-9043-55F31F42819B/appyinxiangcom/22553815/ENResource/p210)]

这是在告诉 Angular 编译器在编译期间读取外部文件,在运行 ng test 命令的时候不会报错,因为运行测试之前是会先编译的,但是在非 cli 环境下进行测试的时候,那个对这个组件的测试可能就会出现报错的现象。

Error: This test module uses the component BannerComponent
which is using a "templateUrl" or "styleUrls", but they were never compiled.
Please call "TestBed.compileComponents" before your test.

此时就需要调用一次 compileComponents() 了,通过调用 compileComponents() 来进行编译。

需要注意的是:compileComponents() 是异步的,所以,一般情况下,要把组件的准备函数beforeEach() 分成两个,一个住同步的,一个是异步的。

  • 异步的
beforeEach(async(() => {
  TestBed.configureTestingModule({
    declarations: [ HeaderComponent ],
  })
  .compileComponents();  // compile template and css
}));
  • 同步的
beforeEach(() => {
    window.localStorage.setItem('menus', JSON.stringify(menus));
    fixture = TestBed.createComponent(HeaderComponent);
    component = fixture.componentInstance;
    router = fixture.debugElement.injector.get(Router);
    translate = fixture.debugElement.injector.get(TranslateService);
    nzI18nService = fixture.debugElement.injector.get(NzI18nService);
    fixture.detectChanges();
    linkDes = fixture.debugElement.queryAll(By.directive(RouterLinkDirectiveStub));
    routerLinks = linkDes.map(de => de.injector.get(RouterLinkDirectiveStub));
  });

建议在需要的时候 compileComponents() 时调用此方法,不需要 compileComponents() 的时候调用它也不会有其他影响。运行 ng test 时永远都不需要调用 compileComponents(),但 CLI 生成的组件测试文件还是会调用它。

带有异步服务的组件

在组件中,有些数据是来自远方服务器的。

使用间谍(Spy)进行测试

对于组件的测试,应该只关心服务的公共 API 是否实现了预计的逻辑。在测试过程中,测试不会向远方服务器发送请求,而是对方法的调用和逻辑的处理进行模拟仿真处理。

  1. 先声明间谍(Spy)
 let loginGetVersionSpy: jasmine.Spy;
  let loginTestData: {};
  const loginService = jasmine.createSpyObj('LoginService', ['getLogin']);

其中 loginTestData 是模拟服务返回的数据对象,loginService 是模拟 LoginService 创建的一个关于 getLogin的Spy对象。

  1. 在TestBed.configureTestingModule中注入
TestBed.configureTestingModule({
      imports: [
        NgZorroAntdModule,
        RouterTestingModule,
        FormsModule,
        HttpClientTestingModule,
      ],
      providers: [
        UtilService,
        PublicDataService,
        TranslateService,
        {provide: NZ_ICONS, useValue: icons},
        {provide: LoginService, useValue: loginService},
      ],
      declarations: [LoginComponent],
      schemas: [NO_ERRORS_SCHEMA]
    }).compileComponents();
    
  1. 使用间谍对象模拟数据返回
 beforeEach(() => {
    fixture = TestBed.createComponent(LoginComponent);
    component = fixture.componentInstance;
    loginTestData = {
      theme: {
        configId: 11,
        name: 'theme',
        value: '0',
        remark: '系统主题方案',
        creatorId: null,
        createTime: null,
        modifierId: null,
        modifyTime: null,
        isdel: 0
      }
    };
    loginGetVersionSpy = loginService.getLogin.and.returnValue(of(loginTestData));
  });

在整个测试中,任何对 getLogin() 方法的调用都会收到一个包含测试模拟数据的可观察对象。 和真正的 getLogin() 方法不同,间谍跳过了服务器,直接返回了一个能立即解析出值的同步型可观察对象(Observable)。

带有输入输出参数的组件

对于有些组件,组件中的部分属性可能是来自于其他组件或者传输给其他组件的。如:

export class LoginComponent implements OnInit {
  @Input() versionId;
  @Output() buildConfDetailsBack = new EventEmitter<any>(); // 返回的信息
  }
  • 对于输入的参数,通过mock数据来模拟数据从其他组件传入

对于组件中 versionId:

describe('LoginComponent', () => {
  let component: LoginComponent;
  let fixture: ComponentFixture<LoginComponent>;
  const loginService = jasmine.createSpyObj('LoginService', ['getLogin']);
  let translate: TranslateService;
  let expectedVersionId: number;
  beforeEach(async(() => {
    TestBed.configureTestingModule({
      imports: [
        NgZorroAntdModule,
        RouterTestingModule,
        FormsModule,
        HttpClientTestingModule,
        TranslateModule.forRoot(),
      ],
      providers: [
        UtilService,
        PublicDataService,
        TranslateService,
        {provide: NZ_ICONS, useValue: icons},
      ],
      declarations: [LoginComponent],
      schemas: [NO_ERRORS_SCHEMA]
    }).compileComponents();
  }));

声明一个 number类型的 对外的versionId。

然后在每个beforeEach()中对组件的属性进行赋值

beforeEach(() => {
    fixture = TestBed.createComponent(LoginComponent);
    component = fixture.componentInstance;
    expectedVersionId = 43;
    component.versionId = expectedVersionId;
    fixture.detectChanges();
  });

然后在进行测试。

  • 对于输出的参数,通过模拟调用触发来返回
it('should test outPut() back info', () => {
    let buildConfDe: DebugElement;
    let buildConfEl: HTMLElement;
    let backInfo: {};
    buildConfDe = fixture.debugElement.query(By.css('.buildConf'));
    component.buildConfDetailsBack.subscribe((buildConfDetails: {}) => backInfo = buildConfDetails);
    buildConfEl = buildConfDe.nativeElement;
    buildConfEl.click();
    expect(backInfo).toBe('match info');
  });

通过fixture中获取 返回信息的点击元素,从中获取元素,并通过点击事件从触发EventEmitter。然后在进行对比。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Angular学习笔记70:Angular项目的单元测试 -- 对组件进行测试 的相关文章

  • 量化选股策略搭建(四)(短期策略搭建)

    量化选股策略搭建 四 短期策略搭建 首先我们需要把选股这个问题转化为一个机器学习问题 那么如何转化成机器学习问题呢 机器学习也分两类问题 1 回归问题 2 分类问题 常规的一些方法是预测股价增长来进行选股 回顾问题 这里我们将其转化为一个分
  • ZooKeeper 分布式协调工具

    目录 一 ZooKeeper 概述 二 ZooKeeper Windows 单机版安装 三 ZooKeeper 集群环境下选举过程 四 ZooKeeper 存储数据的过程 五 ZooKeeper 监听 六 java 操作 ZooKeeper
  • 为什么说python简单_为什么很多人都说 Python 简单?

    Python是一门入门简单 精通困难的编程语言 Python是一门比较高阶的语言 在基本语法和使用方面没有C Java那么复杂 因此 对于入门者来说 很接近于自然语言的表述方式 经过短暂的的学习就可以完成一些简单的工作 但是 我认为如果仅用
  • 面试官:有一个 List 对象集合,如何优雅地返回给前端?我懵了。。

    1 业务背景 业务场景中 一个会话中存在多个场景 即一个session id对应多个scene id和scene name 如果你写成如下的聚合模型类 public class SceneVO private String sessionI
  • [leetcode]Python实现-389. 找不同

    389 找不同 描述 给定两个字符串 s 和 t 它们只包含小写字母 字符串 t 由字符串 s 随机重排 然后在随机位置添加一个字母 请找出在 t 中被添加的字母 示例 输入 s abcd t abcde 输出 e 解释 e 是那个被添加的
  • oracle 数据库基础知识复习

    1 单表的数据查询 1 1指定字段的数据记录查询 select field1 field2 FROM 表名 WHERE CONDITION 例 select t stuname t age t sex from STUINFO t wher
  • curl命令介绍与使用

    curl 全称CommandLine URL 或 CommandLine Uniform Resource Locator 顾名思义 curl命令是在命令行方式下工作 利用URL的语法进行数据的传输或者文件的传输 这个命令行工具现在多用于U
  • 基于Python Django Mysql 开发的宠物用品商城

    最近做的一个程序设计 核心是基于django做一个商城 功能包含登录 注册 商品浏览 购物车 支付模块 支付宝沙箱支付 评价 轮播图 开发环境 Python版本 3 8 7 Django版本 3 1 5 数据库版本 mysql8 数据库管理
  • Hive(二):获取HiveConnection,及重现获取过程中的某些问题。

    为什么80 的码农都做不了架构师 gt gt gt 一 未创建Maven工程 所需jar包都是自己一一找的 结果碰到许多缺包问题 最后我的lib下包为 二 尝试获取HiveConnection 先附上成功获取HiveConnection的代
  • nexus3 Unauthorized问题解决

    环境 Nexus3 version 3 20 1 01 问题 nexus3 在安装完后通过mvn deploy命令 出行 Return code is 401 ReasonPhrase Unauthorized 异常 分析解决 1 mave
  • Hadoop集群启动后,在web:50070端口只有两个datanode节点

    spark集群部署规划 hadoop1 master worker datanode namenode secondarynamenode hadoop resourcemanager nodemanager yarn hadoop2 wo
  • 使用AD14制作PCB的全部流程以及PCB打样流程介绍

    文章目录 1 各PCB打样公司 1 1 深圳嘉立创 1 2 捷配 1 3 华秋 1 4 猎板 2 嘉立创PCB打样流程 2 1 在线下单 2 2 上传PCB文件 2 3 选择板子数量 2 4 工艺参数设置 3 AD元器件库 4 AD14创建

随机推荐

  • 上手Web自动化测试(Python+selenium+unittest)

    从安装库 包和文件配置上手Web自动化测试 Python主要用selenium和unittest库 此外还有用于远程测试的Selenium Server包 浏览器需要配置chromedriver 1 安装selenium库 可以在Pycha
  • Robot Framework (分层实现UI自动化)

    更多资源请前往博主个人网站 http www qabujiaban com Robot Framework介绍与安装 目录 Robot Framework介绍与安装 Robot Framework是什么 什么是自动化测试框架 Robot F
  • linux Ubuntu 引导,重建ubuntu的grub开机引导

    这里将告诉您重建ubuntu的grub开机引导 具体实现方法 pc开机时 在进入系统之前 要先进入的磁盘里安装了grub开机引导的区域 如果是单系统一般不会有问题 但若是多系统像win ubuntu或者ubuntu ubuntu等 有时会出
  • VS2019+Qt Release模式下显示打印信息

    使用VS作为Qt的开发工具 在Debug模式下开发 软件的运行效率不如Release模式下高 所以经常会出现在Release模式下 查看程序的打印输出 只需要在项目属性配置一下即可 点击项目右键 属性 生成事件 生成后事件 在命令行里添加下
  • HJ212-Pack HJ212协议组包实现

    HJ212 Pack HJ212协议组包实现 仓库地址 https gitee com ll0 0ll HJ212 Pack HJ212协议认识 https blog csdn net lblmlms article details 108
  • STM32定时器----TIMx->SR寄存器

    在研究stm32定时器时发现 当进入定时器的中断时 定时器计数器以及中断接收时正常运行的 并没有因为进入中断而停止 具体看以下分析 定时器初始化代码 TIM捕获通道开启宏定义 1 开启 0 关闭 define TIM ICCH1 1 def
  • Vite热更新不起作用

    错误示例 path show component gt import views Show index vue show 目录名 注意路由中是大写开头 这里是小写的 这就是问题所在 Index vue 文件名 这样写目录名或文件名与路由中写
  • Windows10 搭建vs2017OpenGL ES 3.0 开发环境

    前言 更新于2021 06 29 1 首先下载 OpenGL ES 3 0 Programming Guide 随书源码 直接使用CMake工具生成vs2017代码工程 然后使用vs2017打开工程 ES3 Book sln 然而 vs报错
  • mysql多对一、多对多查询实践

    最近做的功能涉及这方面 算是练了一下 首先多对一部分较简单 多的那一方表 多设置一个字段是少的那一方的id 主键 具体查询时候关联查询即可 可设置外键进行级联操作 具体以后做到这个功能再更新 多对多 设备和用户多对多 一个用户可有多台设备
  • 用java编写赛马_java applet 赛马小程序

    昨天写看java书的时候 觉得闷 就写了个小程序自我娱乐一下 技术含量不高 只是自我娱乐而已 下面的代码只要编译出class文件 再写一个HTML格式的文件 调用Arc2Demo2 class 就能看了 该程序实现一个跑马比赛程序 各个选手
  • Translucent System Bar 的最佳实践

    Translucent System Bar 的最佳实践 http mp weixin qq com s biz MzA3MDMyMjkzNg mid 2652262235 idx 1 sn f7ebd354b2ad04064d27e0df
  • 【Docker】基于docker构建深度学习开发环境

    文章目录 1 选择基础镜像 1 1 不同深度学习框架对CUDA和cuDNN的要求 1 2 显卡驱动对CUDA的要求 1 3 深度学习框架对CUDA不同版本要求冲突的解决 2 创建容器并进行基础配置 2 1 创建容器并查看CUDA和cuDNN
  • 某网站面试算法题,今天碰到了,两个大数字相加(足够大)取和

    两个大数相加 1 是整数 2 两个数无限大 long都装不下 3 不能用BigInteger 4 不能用任何包装类提供的运算方法 5 两个数都是以字符串的方式提供 面试答卷直接写下 此处空白位置太小 写不下 请求机试 果然给我一台应该是 爬
  • Spring 循环依赖的三级缓存

    在Spring Bean 的生命周期中 里面有一步就是填充属性 而填充属性之前会判 属性对象是否被当前对象循环依赖 当发现属性对象被循环依赖的时候会进行aop 被命中 并且生成属性对象的代理对象 未命中目标对象 循环依赖是如何形成的 当 对
  • 基于PSIM及其DLL模块的单相全桥并网逆变器仿真

    摘要 本文简单地介绍了单相全桥并网逆变器的闭环控制原理 利用PSIM软件来进行仿真实验 关键词 单相 闭环控制 PSIM DLL 锁相环 过零检测 进网电流反馈 SPWM 因在研究过程中参考的不少文献忘记标记了 所以无法一一列出 如有侵权
  • 【elasticsearch】ES 单分片使用 From/Size 分页遇到重复数据

    1 概述 ES 单分片使用 From Size 分页遇到重复数据 常规情况下 ES 单分片使用 From Size 是不会遇到数据重复的 数据重复的可能原因有 没有添加排序 添加了按得分排序 但是查询语句全部为 filter 过滤条件 此时
  • SpringSecurity常见面试题汇总(超详细回答)

    1 什么是Spring Security 核心功能 Spring Security是一个基于Spring框架的安全框架 提供了完整的安全解决方案 包括认证 授权 攻击防护等功能 其核心功能包括 认证 提供了多种认证方式 如表单认证 HTTP
  • Android的关于高德地图加载谷歌瓦片,并缓存本地的功能.

    最近开发的Android的App需要使用到卫星图 不过发现国内现有的百度 高德的卫星图对郊区图层支持的不好 只能使用谷歌的卫星图 在尝试使用谷歌的Google Map API for Android后又发现去要手机安装谷歌服务 并且有可能用
  • batchsize的选择和学习率调整

    batchsize的选择和学习率调整 增大Batch Size的好处 数据的处理速度加快 跑完一次 epoch 全数据集 所需的时间减少 在一定范围内 一般来说 Batch Size 越大 其确定的下降方向越准 引起训练震荡越小 尤其是网络
  • Angular学习笔记70:Angular项目的单元测试 -- 对组件进行测试

    对组件进行测试 对组件绑定的测试 例如在一个组件中 一个组件中模版里有一个标题的是 h2 class title title h2 组件的类文件中对应绑定了一个类文件中的属性 测试这个绑定的数据 it should render title