Angular单元测试:Karma和Jasmine

2024-12-03328阅读0评论ADMIN
Angular单元测试:Karma和Jasmine

Angular单元测试检查Angular应用程序中的隔离代码片段。它允许用户在不中断应用程序的任何其他部分的情况下添加新功能。Jasmine是一个Javascript测试框架,Karma是一个基于Node的JavaScript代码的测试工具,可跨多个真实浏览器进行测试 。本博客将帮助您开始使用Karma和Jasmine进行Angular单元测试。

Angular单元测试简介

首先,您必须在您的计算机上安装Angular。这是您需要开始安装Angular的地方。如果您已经安装了Angular,请随意跳过下一步。

创建和管理Angular项目非常容易。有各种竞争库、框架和工具可以解决这些问题。Angular团队创建了Angular CLI,这是一个用于简化Angular项目的命令行工具。Angular CLI通过npm安装,因此您需要在您的计算机上安装Node。

安装Node后,您可以在终端中运行以下命令。

安装完成所需的时间可能会有所不同。完成后,您可以在终端中输入以下命令来查看Angular CLI的版本。

现在您已经安装了Angular CLI,可以准备创建一个Angular示例应用程序。在您的终端中运行以下命令。

ng new angular-unit-test-application

执行该命令后,您将被询问是否要添加Angular路由。键入Y并按ENTER。然后,您将被要求在应用程序的样式表格式之间进行选择。这将需要几分钟时间,一旦完成,您将转到您的测试应用程序。

单元测试测试了代码的隔离单元。单元测试旨在回答诸如:

  • 排序函数是否按正确的顺序对列表进行了排序?
  • 我是否能正确地思考逻辑?

为了回答这些问题,关键是要隔离正在测试的代码单元。这是因为当您测试排序函数时,您不希望被迫创建相关的部分,比如进行任何API调用以获取实际数据库数据进行排序。

您已经知道单元测试测试软件或应用程序的各个组件。这样做的主要动机是检查所有单独的部分是否按预期工作。单元是可以测试的软件的最小可能组件。通常,它有几个输入和一个输出。

让我们进入Angular Web应用程序测试部分。

在您的终端中运行以下命令。

等待几秒钟后,您将看到一个新的浏览器窗口打开,显示如下所示的页面。

解析Karma和Jasmine在Angular单元测试中的作用

什么是Karma测试运行器?

Karma是由Angular JS团队开发的测试自动化工具,因为使用当前工具测试他们自己的框架特性变得困难。因此,他们开发了Karma,并将其转换为Angular开发的应用程序的默认测试运行器。除了与Angular兼容外,它还提供了灵活性,可以根据您的工作流程定制Karma。它可以选择在不同的浏览器和设备(如平板电脑、手机等)上测试您的代码。Karma为您提供了将Jasmine替换为其他测试框架(如MochaQUnit)的选项。

以下是示例项目中karma.conf.js文件的内容。

什么是Jasmine? Jasmine是一个免费的开源行为驱动开发(BDD)框架,用于测试JavaScript代码,并且与Karma兼容。与Karma一样,它也是Angular文档中建议的测试框架。

测试运行的流程如下,

测试组件 add-organization.component.ts

// 代码块内容不需要翻译,原文输出

add-organization.component.spec.ts

// 代码块内容不需要翻译,原文输出

在这个组件中,你可以看到下面列出的一些测试事项:

  1. Angular响应式表单验证
  2. 条件变量和路由调用
  3. 多种情况覆盖分支和语句
  4. 弹出模态框,包括确认和取消
  5. 提交表单数据并调用post API,同时也会涉及错误处理部分
  6. 使用API调用获取组织详情

所有这些事项都将在我们的规范文件中进行测试。你可以在上面的图像中看到,它将涵盖所有的语句、函数、分支等。

从上面的代码片段中,你会注意到多个事项。下面是每个事项的解释:

  1. 我们使用describe来开始我们的测试,并在其中给出了我们要测试的组件的名称。
  2. 我们可以在每个规范执行之前执行一些代码片段。这个功能对于在应用程序中运行通用代码非常有用。
  3. beforeEach中,我们有TestBed.ConfigureTestingModuleTestBed设置了适合我们测试的配置并初始化了环境。ConfigureTestingModule设置了允许我们测试组件的模块。你可以说它为我们的测试环境创建了一个模块,并在其中声明了导入和提供者。

测试服务

1. Organization.service.ts

import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { HttpBaseService } from '../shared/services/httpbase/httpbase.service';
import { LanguageService } from '../shared/services/language/language.service';

@Injectable({
providedIn: 'root'
})
export class OrganizationService extends HttpBaseService {
constructor(httpClient: HttpClient, languageService: LanguageService) {
super(httpClient, languageService);
}

prepareOrganizationListResponse(resList: any[]) {
let organizationList: any = [];
let organization: any = {};

resList.forEach(list => {
organization.lastName = list.lastName,
organization.firstName = list.firstName,
organization.email = list.email,
organization.isActive = list.isActive

organizationList.push(organization);
});
return organizationList;
}

prepareOrganizationDetailsResponse(res: any) {
return {
lastName: res.lastName,
firstName: res.firstName,
email: res.email,
isActive: res.isActive
};
}
}

2. Organization.service.spec.ts

import { SharedModule } from 'src/app/shared/modules/shared.module';
import { HttpClientModule } from '@angular/common/http';
import { TestBed } from '@angular/core/testing';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { TranslateModule, TranslateLoader, TranslateFakeLoader, TranslateService } from '@ngx-translate/core';
import { HttpBaseService } from '../shared/services/httpbase/httpbase.service';
import { SharedService } from '../shared/services/shared.service';
import { OrganizationService } from './organization.service';
import { OrganizationConfigurationApi, OrganizationListItemUI } from './organization.model';

describe('OrganizationService', () => {
let service: OrganizationService;

beforeEach(() => {
TestBed.configureTestingModule({
imports: [
HttpClientModule,
SharedModule,
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useClass: TranslateFakeLoader
}
}),
],
providers: [
TranslateService,
HttpBaseService,
SharedService,
{ provide: MAT_DIALOG_DATA, useValue: {} },
{ provide: MatDialogRef, useValue: {} }
]
}).compileComponents();
service = TestBed.inject(OrganizationService);
});

it('should be created', () => {
expect(service).toBeTruthy();
});

it('should be return properly formatted organization list response', () => {
let organization: any = {};
organization.lastName = 'lastName',
organization.firstName = 'firstName',
organization.email = 'test@gmail.com',
organization.isActive = true,

expect(service.prepareOrganizationListResponse(
[
{
lastName: 'lastName',
firstName: 'firstName',
email: 'test@gmail.com',
isActive: true,
}
]
)).toEqual([organization]);
});

it('should be return organization details response', () => {
expect(service.prepareOrganizationDetailsResponse({
lastName: 'lastName',
文章版权声明:除非注明,否则均为猿易帮原创文章,转载或复制请以超链接形式并注明出处。

发表评论

快捷回复: 表情:
AddoilApplauseBadlaughBombCoffeeFabulousFacepalmFecesFrownHeyhaInsidiousKeepFightingNoProbPigHeadShockedSinistersmileSlapSocialSweatTolaughWatermelonWittyWowYeahYellowdog
验证码
评论列表 (暂无评论,328人围观)

还没有评论,来说两句吧...

目录[+]

取消
微信二维码
微信二维码
支付宝二维码