Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >在单元测试中从不调用订阅内的角度函数

在单元测试中从不调用订阅内的角度函数
EN

Stack Overflow用户
提问于 2020-12-15 13:28:00
回答 1查看 428关注 0票数 0

我正在尝试测试我的导航功能是否被称为删除车辆。但它似乎从来没有打过电话。我认为这可能与它是一个异步函数有关,但即使当我等待完整订阅完成时,它也不起作用。

.ts:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
deleteVehicle(): void {
    if (confirm('Bent u zeker dat u deze wagen wilt verwijderen?')) {
      this.apiService.deleteVehicle(this.selectedVehicle.id).subscribe(() => this.navigateToListVehicleComponent());
    }
  }

spec.ts:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
beforeEach(() => {
    fixture = TestBed.createComponent(VehicleDetailsComponent);
    component = fixture.componentInstance;

    apiService = TestBed.get(ApiService);
    fixture.detectChanges();
});
describe('#deleteVehicle', () => {
    it('should navigate to list vehicle component', fakeAsync(() => {
      spyOn(window, 'confirm').and.returnValue(true);
      spy = spyOn(apiService, 'deleteVehicle').withArgs(component.selectedVehicle.id).and.callThrough();
      let navigateSpy = spyOn(component,'navigateToListVehicleComponent').and.callThrough();

      component.deleteVehicle();
      tick();
      expect(spy).toHaveBeenCalled();
      expect(navigateSpy).toHaveBeenCalled();
    }));
  });

service.ts:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
private deleteFromAPI(url): any {
    return this.http
    .delete(this.BASE_API_URL + url)
    .pipe(catchError(this.handleError));
}
deleteVehicle(id: number): any {
    return this.deleteFromAPI('vehicle/' + id);
}

在我的测试床中,我导入了HttpClientTestingModule。

错误:预期已调用spy navigateToListVehicleComponent。

有人知道我做错了什么吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-12-21 05:31:27

我的测试策略是将apiService.deleteVehicle方法存根,这样它就不会有副作用(通过网络发送真正的HTTP请求)。

使用angular v11+的单元测试解决方案:

example.component.ts

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import { Component } from '@angular/core';
import { ApiService } from './api.service';

@Component({})
export class ExampleComponent {
  selectedVehicle = {
    id: 1,
  };
  constructor(private apiService: ApiService) {}
  navigateToListVehicleComponent() {
    console.log('navigateToListVehicleComponent real implementation');
  }

  deleteVehicle(): void {
    if (confirm('Bent u zeker dat u deze wagen wilt verwijderen?')) {
      this.apiService
        .deleteVehicle(this.selectedVehicle.id)
        .subscribe(() => this.navigateToListVehicleComponent());
    }
  }
}

api.service.ts

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { of } from 'rxjs';
import { catchError } from 'rxjs/operators';

@Injectable()
export class ApiService {
  BASE_API_URL = 'http://localhost';
  constructor(private http: HttpClient) {}

  private deleteFromAPI(url): any {
    return this.http
      .delete(this.BASE_API_URL + url)
      .pipe(catchError(this.handleError));
  }
  private handleError(err) {
    return of(err);
  }
  deleteVehicle(id: number): any {
    return this.deleteFromAPI('vehicle/' + id);
  }
}

example.component.spec.ts

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import { HttpClient, HttpClientModule } from '@angular/common/http';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { of } from 'rxjs';
import { ApiService } from './api.service';
import { ExampleComponent } from './example.component';

fdescribe('#deleteVehicle', () => {
  let apiService: ApiService;
  let fixture: ComponentFixture<ExampleComponent>;
  let component: ExampleComponent;

  beforeEach(
    waitForAsync(() => {
      TestBed.configureTestingModule({
        declarations: [ExampleComponent],
        imports: [HttpClientModule],
        providers: [ApiService, HttpClient],
      })
        .compileComponents()
        .then(() => {
          fixture = TestBed.createComponent(ExampleComponent);
          apiService = TestBed.get(ApiService);
          component = fixture.componentInstance;
          fixture.detectChanges();
        });
    })
  );
  it('should navigate to list vehicle component', () => {
    const confirmSpy = spyOn(window, 'confirm').and.returnValue(true);
    const deleteVehicleSpy = spyOn(apiService, 'deleteVehicle')
      .withArgs(component.selectedVehicle.id)
      .and.returnValue(of('deleteVehicle fake implementation'));

    let navigateSpy = spyOn(
      component,
      'navigateToListVehicleComponent'
    ).and.stub();

    component.deleteVehicle();

    expect(confirmSpy).toHaveBeenCalledOnceWith(
      'Bent u zeker dat u deze wagen wilt verwijderen?'
    );
    expect(deleteVehicleSpy).toHaveBeenCalledOnceWith(1);
    expect(navigateSpy).toHaveBeenCalled();
  });
});

单元测试结果:

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65306853

复制
相关文章
Jest单元测试之旅—实践总结
维基百科对于单元测试的定义:是针对程序模块(软件设计的最小单位)来进行正确性检验的测试工作。程序单元是应用的最小可测试部件。在过程化编程中,一个单元就是单个程序、函数、过程等;对于面向对象编程,最小单元就是方法,包括基类(超类)、抽象类、或者派生类(子类)中的方法。
gary12138
2022/10/05
10.4K0
Jest单元测试之旅—实践总结
【干货分享】微信小程序单元测试攻略
导语 本文作者是腾讯社交增值产品部高级前端工程师林毅雄,对前端开发领域颇有研究。接下来,本文将从测试框架、实战、覆盖率、踩坑等方面分享一下微信小程序的单元测试经验,希望能帮到大家。 01 写作初衷 大家先看看A公司与B公司的数据对比: 从上图可以看出,B公司的单元测试做的比较好,每百行error数也比A公司的项目低。 总体来说,单元测试有以下一些好处: 1,及早发现代码错误,提高代码质量和可维护性。 2,代码变更时可以快速进行检查。 然而要做好测试也有一定的困难: 1,花费时间长。 2,被测代码
WeTest质量开放平台团队
2021/12/17
2.8K0
JavaScript测试教程–part 4:模拟 API 调用和模拟 React 组件交互[每日前端夜话0xEA]
今天,我们进一步测试 React 组件。它涉及模拟组件交互和模拟 API 调用。你将学到两种方法,开始吧!
疯狂的技术宅
2019/11/25
3.8K0
JavaScript测试教程–part 4:模拟 API 调用和模拟 React 组件交互[每日前端夜话0xEA]
JavaScript 测试系列实战(三):使用 Mock 模拟模块并处理组件交互
在之前的两篇教程中,我们学会了如何去测试最简单的 React 组件。在实际开发中,我们的组件经常需要从外部 API 获取数据,并且组件的交互逻辑也往往更复杂。在这篇教程中,我们将学习如何测试更复杂的组件,包括用 Mock 去编写涉及外部 API 的测试,以及通过 Enzyme 来轻松模拟组件交互
一只图雀
2020/09/10
4.8K0
使用Jest测试包含setTimeout调用的函数踩坑记录
前两天给一个包含setTimeout调用的函数写单元测试,在使用fake timer的时候遇到了问题,记录一下。
雪之下Perqin
2021/08/26
7K0
那些年错过的React组件单元测试(上)
关于前端单元测试,其实两年前我就已经关注了,但那时候只是简单的知道断言,想着也不是太难的东西,项目中也没有用到,然后就想当然的认为自己就会了。
前端森林
2021/04/12
5K0
React Hook测试指南
在React为什么需要Hook中我们探讨了React为什么需要引入Hook这个属性,在React Hook实战指南中我们深入了解了各种Hook的详细用法以及会遇到的问题,在本篇文章中我将带大家了解一下如何通过为自定义hook编写单元测试来提高我们的代码质量,它会包含下面的内容:
进击的大葱
2022/08/22
1.7K0
编写接口请求库单元测试与 E2E 测试的思考
最近在写适配 Mx Space Server 的 JS SDK。因为想写一个正式一点的库,以后真正能派的上用场的,所以写的时候尽量严谨一点。所以单测和 E2E 也是非常重要。
Innei
2021/12/28
1.1K0
干货 | 携程租车React Native单元测试实践
琨玮,携程高级前端开发工程师,从事React Native/Web前端的开发及维护工作,喜欢研究新技术。
携程技术
2020/02/18
6.2K0
干货 | 携程租车React Native单元测试实践
[译] React 测试驱动开发:从用户故事到产品
原文:https://www.toptal.com/react/tdd-react-user-stories-to-development
江米小枣
2020/08/10
3.3K0
[译] React 测试驱动开发:从用户故事到产品
React 设计模式 0x8:测试
测试在每个 Web 应用程序中都非常重要,即使在 React 中也是如此,特别是在其组件方面。
Cellinlab
2023/05/17
1.8K0
聊聊jest的IdleConnectionReaper
jest-common-6.3.1-sources.jar!/io/searchbox/client/config/idle/IdleConnectionReaper.java
code4it
2019/04/22
9820
聊聊jest的IdleConnectionReaper
聊聊jest的NodeChecker
jest-common-6.3.1-sources.jar!/io/searchbox/client/config/discovery/NodeChecker.java
code4it
2019/04/21
1.1K0
聊聊jest的NodeChecker
Struts2学习---基本配置,action,动态方法调用,action接收参数 动态方法调用action接收参数
首先我们先来直接配置,然后再来讲原理: 第一步:jar包的引入: 我们可以到struts2的官网上下载: http://struts.apache.org/download.cgi#struts
MindMrWang
2018/04/16
1.7K0
聊聊jest的NodeChecker
jest-common-6.3.1-sources.jar!/io/searchbox/client/config/discovery/NodeChecker.java
code4it
2019/05/06
8090
React Native 持续部署实践— push 代码构建出新版的 Growth
最近我们正在使用 React Native 来重写 Growth 应用,GitHub 地址:growth-ng 。作为一个『咨询师』,我要再一次地切换技术栈,从混合应用开发转向 React Native。 重写 Growth 项目,由于业务内容繁多,也因此变成了一个庞大的工程。为了减少开发的时候,不断也开现一些错误,因此花了一段时间来探索:APP 端的持续部署。因此在这一篇文章里, 我们将介绍基于下面的几个框架来搭建持续集成: React Native 与持续集成服务器 Travis CI 的使用 单元测试
Phodal
2018/01/29
2.2K0
React 组件测试技巧
在这个页面上,我们将主要使用函数组件。然而,这些测试策略并不依赖于实现细节,它对于 class 组件也同样有效。
Fonkie
2019/08/31
4.9K0
点击加载更多

相似问题

调用Jest spyOn函数

30

jest.spyOn未调用

11

Jest spyOn不识别函数调用

12

Jest spyOn.mockImplementation调用实际方法

111

Jest ( Received ):测试内部组件函数:错误:预期调用数:>= 1接收到的呼叫数:0

16
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文