角度异步等待中的单元测试位置

2024-02-25

我使用 Angular 9+ 与 karma 测试运行器和 jasmine 测试框架进行单元测试。

我只想进行单元测试app component其中有一个依赖注入:

app.component.ts

import { Component, EmbeddedViewRef } from '@angular/core';
import * as moment from 'moment-timezone';
import { OtherServiceService } from './other-service.service';
import { Location } from '@angular/common';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
    constructor(private sampleService: OtherService, private location: Location){}

    async func(){
        await this.sampleService.func2().toPromise();
        console.log('Async call completed');
        this.location.go('/index.html');
    }
}

other-service.service.ts

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Injectable({
  providedIn: 'root'
})
export class OtherServiceService {

  constructor(private http: HttpClient) { }

  func2(){
    return this.http.post('' , null);
  }
}

到目前为止我尝试过的单元测试:

import { NO_ERRORS_SCHEMA } from '@angular/core';
import { TestBed, async, fakeAsync, tick } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { of } from 'rxjs';
import { AppComponent } from './app.component';
import { OtherServiceService } from './other-service.service';

const locationStub = {
  go: jasmine.createSpy('go')
}

describe('AppComponent', () => {
  let otherServiceStub;
  let fixture, component;
  beforeEach(async(() => {
    otherServiceStub = jasmine.createSpyObj(['func2']);

    TestBed.configureTestingModule({
      imports: [
        RouterTestingModule
      ],
      declarations: [
        AppComponent
      ],
      providers: [
        {provide: OtherServiceService , useValue: otherServiceStub},
        {provide: Location, useValue: locationStub}
    ],
      schemas: [NO_ERRORS_SCHEMA]
    }).compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(AppComponent);
    component = fixture.componentInstance;
  });

  it('should create the app', () => {
    const app = fixture.componentInstance;
    expect(app).toBeTruthy();
  });

  it('should check for correct logs',fakeAsync(() => {
    otherServiceStub.func2.and.returnValue(of('Garbage'));
    const location = fixture.debugElement.injector.get(Location);
    let spyObj = spyOn(console,'log');
    component.func();
    tick();
    expect(spyObj).toHaveBeenCalledWith('Async call completed');
    expect(location.go).toHaveBeenCalledWith('/index.html');
 }));


});

运行 ng test --code-coverage 时,它​​总是显示错误Expected spy go to have been called with: [ '/index.html' ] but it was never called..

在覆盖率报告上,它显示该行已被覆盖 (this.location.go) ,但测试失败,我似乎无法理解为什么。我也得到了帮助this https://stackoverflow.com/questions/48202042/angular-how-to-test-a-component-which-requires-a-location,但没有成功。

UPDATE 1.0:

我已经按照@AliF50的建议尝试过:

  async func(){
    await this.sampleService.func2().toPromise();
    console.log('Async call completed');
    this.location.go('/index.html');
    console.log('After location go in component');
  } 
  it('should check for correct logs',fakeAsync(() => {
    otherServiceStub.func2.and.returnValue(of('Garbage'));
    let spyObj = spyOn(console,'log');
    component.func();
    tick();
    const location = fixture.debugElement.injector.get(Location);
    expect(spyObj).toHaveBeenCalledWith('Async call completed');
    console.log('Before location go in test');
    expect(location.go).toHaveBeenCalledWith('/index.html');
    console.log('After location go in test');
 }));

但令我惊讶的是none of the console logs正在打印,即使它显示的行已被覆盖。

UPDATE 2.0:

正如@AliF50 所建议的:

  it('should check for correct logs',fakeAsync(() => {
    otherServiceStub.func2.and.returnValue(of('Garbage'));
    let spyObj = spyOn(console,'log').and.callThrough();
    component.func();
    tick();
    const location = fixture.debugElement.injector.get(Location);
    expect(spyObj).toHaveBeenCalledWith('Async call completed');
    console.log('Before location go in test');
    expect(location.go).toHaveBeenCalledWith('/index.html');
    console.log('After location go in test');
 }));

All the console logs正在打印,但错误仍然存​​在。

UPDATE 3.0: 有人运气好吗?这仍然是一个悬而未决的问题

UPDATE 4.0: 感谢安德烈。问题现在解决了。


js中的promises和asyncawait存在问题,它们无论如何都无法同步。因此,如果您的代码涉及使用 async/await,正确的方法是使您的测试函数也异步。

it('should check for correct logs',async () => {
   otherServiceStub.func2.and.returnValue(of('Garbage'));
   let spyObj = spyOn(console,'log').and.callThrough();
   await component.func();
   expect(spyObj).toHaveBeenCalledWith('Async call completed');
});

带有位置检查的整个测试应该看起来像

const locationStub = {
  go: jasmine.createSpy('go')
}
...
it('should check for correct navigation', async () => {
  otherServiceStub.func2.and.returnValue(of('Garbage'));
  await component.func();
  const location = TestBed.get(Location); // or just locationStub can be referred directly here
  expect(location.go).toHaveBeenCalledWith('/index.html');
});
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

角度异步等待中的单元测试位置 的相关文章

  • 如何在Python中模拟依赖关系

    我是 python 单元测试框架的新手 并且在模拟依赖项方面存在很多困惑 我正在尝试为类的以下成员函数编写单元测试 check something class Validations def check something self abc
  • Mat-自动完成表单控件名称

    我在 Mat Autocomplete 上使用 formControlName 时遇到问题 我不知道为什么 但我的 formControlName 不会发送数据 我是否写错了 当我尝试从 HTML 中删除 formControl 时 它总是
  • 如何为有时异步的操作创建和实现接口

    假设我有数百个类 它们使用 计算 方法实现公共接口 一些类将执行异步 例如读取文件 而实现相同接口的其他类将执行同步代码 例如将两个数字相加 为了维护和性能 对此进行编码的好方法是什么 到目前为止我读到的帖子总是建议将异步 等待方法冒泡给调
  • Angular 4:在订阅中收到错误消息

    在服务中 有这样的代码 getUser id return this http get http id map res gt res json 在组件中 this myService getUser this id subscribe cu
  • 试驾 Nancy 模块

    好的 我喜欢 NancyFx 用这么几行代码编写一个 Web 应用程序真是太棒了 但是如何在单元级别上测试驱动 NancyModule 请注意 我知道优秀的测试框架 https github com NancyFx Nancy wiki T
  • Ionic 2 beta 11:初始化日期时间组件以考虑本地时区

    我遇到了问题datetimeIonic 2 beta 11 中的组件 根据我在离子 API 文档 http ionicframework com docs v2 api components datetime DateTime 我应该从 D
  • Facebook JS SDK渐进式网络应用程序问题

    我有一个使用 Angular 4 构建的渐进式 Web 应用程序 我的问题是从主屏幕应用程序使用时 Facebook 登录对话框不会自动关闭 在 Chrome 浏览器中打开时它工作得很好 但是当我从安装的主屏幕应用程序使用它时 对话框窗口打
  • 关注新添加的输入元素

    我有一个新的 Angular 2 应用程序 其中包含以下列表input盒子 当用户按下返回键时 我添加一个新的input紧接着他们当前正在编辑的框后面的框 或者更确切地说 我 异步 向模型中的数组添加一个新条目 这会导致 Angular 2
  • 根据屏幕尺寸更改 md-grid-list 的布局或 cols 值

    我正在使用的网格列表角材2 https material angular io components grid list examples 这是笨蛋https plnkr co edit 0v9R3e4x3tThh85147x7 p pre
  • Angular2:禁用表单构建器的元素

    我试图在声明后禁用表单构建器的一个元素 因为加载视图后我必须验证某些内容 所以这是我的表单构建器声明 ionViewDidLoad this purchaseDataForm this formBuilder group kms Valid
  • Angular AOT 编译错误“无法确定类组件的模块”

    我有一个 Angular 4 3 2 应用程序 我想在其上执行 AOT 构建 应用程序是使用创建的 angular cli 我有两个组件ng generate以及一个将两者作为声明包含在其中的模块 import PrivateCompone
  • 无法绑定到“属性 X”,因为它不是“子组件”的已知属性

    在我的项目中 我有一个通用类和一些从该类继承的其他组件 BaseRdnInput ts Injectable export abstract class BaseRdnInput implements ControlValueAccesso
  • 如何自定义 Google 测试失败消息?

    我编写了一个如下所示的 Google 测试 它将一些计算值与 CSV 文件中预期存储的值进行比较 class SampleTest public testing Test public void setupFile const std st
  • 如何在 Angular 2 中实现 D3

    我想将这段代码从 d3 js 实现到 Angular 2 组件 但我不知道如何将 js 文件调用到组件 ts 文件中 我找到了一些折线图的代码 包括index html和lineChart js 我怎样才能调用javascriptngAft
  • Angular Service Worker - 无法加载资源:服务器响应状态为 504(网关超时)

    我正在使用Angular CLI 1 6 6 and angular service worker 5 2 5 in our Angular 5 2 5应用程序 除了在我们的生产环境中弹出一条错误消息之外 本地精简版服务器以及生产服务器上的
  • 编辑时可以在文本框控件内使用 Angular 的管道格式化程序吗?

    我已经声明了一种将大数字分成三位数组的格式 并像这样经常使用它 div Huge number i am huge make threesome div 现在 有一个对相应功能的请求 但在像这样的输入控件中实现
  • 单元测试魔术方法

    当涉及到 PHP 中魔术方法的单元测试实现时 调用这些方法的推荐方法是什么 我看到三个可用选项 显式 直接调用它们 object gt get someValue 间接调用它们 使用任何旨在触发它们的操作 object gt someVal
  • 将模板添加为innerHTML 时,Angular 2 绑定/事件不起作用

    我正在尝试创建一个可配置的可重用表 单元格可以配置为具有 html 模板 我正在配置列 Review 拥有带有带有点击事件的锚标记的 html 模板 审核 行 到目前为止 我尝试将此模板作为innerHTML 插入 但所有角度绑定都不起作用
  • 如何在 Node 中使用 Mysql2 使用 async 和 pool 获取 MySQL 的 insertId?

    我正在尝试将 async wait 与 mysql2 和池一起使用 但我认为我做错了 下面是我的代码 正如我所说 我不确定我是否在这里做事 const pool mysql createPool host localhost user ro
  • 正确的单元测试技术

    在使用 TDD 时 我发现自己需要测试一个包含查找值的常量 最终 哈希图 请查看更新中出现这种情况的原因 见下文 private static final Map

随机推荐