如何使用 Injector 在函数中模拟注入服务

2024-01-05

在 Angular 7.x 中,我有一个全局错误处理,可以使用注入器注入他的服务。因此每个函数都有一个对注入器的引用,如下所示:

import { ErrorHandler, Injectable, Injector, NgZone } from '@angular/core';
import { Router } from '@angular/router';
import { LoggingService } from '../logging/logging.service';
import { EnvironmentService } from '../services/environment.service';

@Injectable()
export class GlobalErrorHandler implements ErrorHandler {
  constructor(private readonly injector: Injector, private readonly zone: NgZone) {}

  handleError(error: any): void {
    // Handle Client Error (Angular Error, ReferenceError...)
    this.processError(error);

    throw error;
  }

  processError(error: any): void {
    const environmentService = this.injector.get(EnvironmentService);
    const environment = environmentService.getEnvironment();
    if (!environment.production) {
      console.error(error);
    } else {
      // Log the expection to the logger
      this.logException(error);

      this.zone.run(() => {
        this.navigateToErrorPage(error);
      });
    }
  }

  private logException(error: any): void {
    const loggingService = this.injector.get(LoggingService);
    loggingService.logException(error);
  }

  private navigateToErrorPage(error: any): void {
    const router = this.injector.get(Router);
    router.navigate(['/500'], { queryParams: { error } });
  }
}

如您所见,在processError函数我注入环境服务。该服务的唯一目标是能够在我的规范测试中模拟环境。我在另一个服务测试中执行此操作,但我将其与依赖项注入一起使用,而不是与this.injector.get(...)功能。

有谁知道我是如何嘲笑这个的?

it('should log the error if the environment is in production', () => {
  // Arrange
  const environmentSpy = jasmine.createSpyObj('EnvironmentService', 'getEnvironment'); ??? How do I mock this ???

  const error: Error = new Error('New Error');
  spyOn<any>(errorHandler, 'logException');
  // Act
  errorHandler.processError(error);

  // Assert
  expect(errorHandler['logException']).toHaveBeenCalledWith(error);
});

您可以监视 Injector 并返回一个假类来代替具有自定义的 EnvironmentServicegetEnvironment() method:

spyOn(TestBed.get(Injector), 'get').and.callFake((token) => {
    if (token === EnvironmentService) {
        // Return a mocked EnvironmentService class
        return {
            getEnvironment: () => { return { production: true }; }
        };
    } else {
        // Otherwise, return whatever was originally defined in the TestBed
        return TestBed.get(token);
    }
});

或者,您可以使用真正的注入器并监视环境服务:

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

如何使用 Injector 在函数中模拟注入服务 的相关文章

随机推荐

  • 如何在 Symfony Response 中包含 Web 调试工具栏?

    当我渲染模板并从控制器返回响应时 页面底部有一个漂亮的 Web 调试工具栏 当我不使用模板并通过自己创建 Response 对象返回响应时 是否可以使此栏出现 应该足以确保有一个有效的 响应 HTML 代码中包含的块 如果主体部分丢失 则不
  • 如何从一个 SELECT 语句插入多个表

    我正在尝试从一个 select 语句插入多个表 是否可以 这就是我在这里尝试做的事情 insert into table1 Name Address insert into table2 Name Address select Name A
  • 为什么设置初始化值会阻止在 TensorFlow 中将变量放置在 GPU 上?

    当我尝试运行以下非常简单的 TensorFlow 代码时出现异常 尽管我实际上是从文档中复制了它 import tensorflow as tf with tf device gpu 0 x tf Variable 0 name x ses
  • anaconda下导入OpenCV失败

    我正在尝试在 Anaconda 下使用 OpenCV for Python2 7 8 final 0 我全新安装了 Anaconda 然后使用 conda 工具导入了 OpenCV 的最新 win 64 发行版 2 4 9 1 np19py
  • Nhibernate QueryOver Orderby

    我试图在 queryover 调用上解耦 orderby 但这无法编译 protected static void AddOrder
  • C# 如何禁用某个按键

    当按下 ENTER 键时 如何防止插入符号转到文本框中的下一行 换句话说 如何禁用文本框中的 ENTER 或 RETURN 键 你可以写OnKeyDown事件 你可以使用e SuppressKeyPress告诉 NET 您处理该密钥 像这样
  • 如何使用 C++ std::ostream 和类似 printf 的格式?

    我正在学习C cout是一个实例std ostream班级 如何用它打印格式化字符串 我仍然可以使用printf 但我想学习一种正确的 C 方法 可以利用 C 的所有优点 我认为这应该是可能的std ostream 但我找不到正确的方法 在
  • 如何使用 socket.io 判断哪个套接字连接单击了按钮?

    如果页面上有一个按钮 并且您想确保在另一个套接字单击其按钮之前无法再次单击该按钮 如果套接字 a 单击 我应该禁用该按钮 直到另一个套接字发送一条消息 表明他们单击了按钮 然后返回第四个 buttonTurns on click funct
  • 如何在 Archlinux 中使用 gcc 7.2 编译 gcc 6.4.0

    我正在尝试在 Archlinux 中与 gcc 7 2 独立编译 gcc 6 4 0 配置如下 configure prefix INSTALL PREFIX enable languages c c fortran enable thre
  • Lambda 函数作为构造函数中 std::function 的默认参数

    我希望在类的构造函数中为函子参数提供一个默认函子 作为一个最小的例子 我想出了一个应该作为过滤器的类 它过滤类型的元素T如果过滤器函数返回 true 过滤器函数应该在构造函数中提供 默认为 接受所有 过滤器函数 template
  • 如何使用循环在每个 div 中添加类

    这是我的结构 我想在每两个 div 中添加奇偶类 所以我怎样才能使用 JavaScript 循环实现这个结构我尝试了一切 但我什么也没得到我正在学习 JavaScript 循环所以任何人都请帮助我 var i 0 CollectionInn
  • 动态代码执行:字符串 -> 运行时代码 VB.net

    我正在尝试在运行时执行字符串内的一些代码 IE Dim code As String IIf 1 2 True False 我如何运行里面的代码code细绳 正如 ElektroStudios 所说 正确的方法是使用CodeDom编译器 h
  • ExtJS 6 plugin.rowwidget 在创建行主体组件时获取绑定记录

    我有一个网格Ext grid plugin RowWidget http docs sencha com extjs 6 2 0 classic Ext grid plugin RowWidget html 当我展开行时 我必须使用行记录数
  • Jquery UI 选项卡:下一个和上一个基于选择框启用/禁用

    我目前正在使用 Jquery UI 选项卡 我只能使用下一个 上一个按钮进行操作 这将迫使用户按顺序浏览选项卡 在我的第一个选项卡中 我有一组动态选择框 我试图让用户在启用 下一步 按钮之前从对应的类别及其子类别中选择一个类别及其子类别 但
  • 在 C++ 中将结构体作为构造函数参数传递

    我已尽我所能 但在这个特定主题上找不到太多内容 我必须采用大量变量 可能是多个对象 并将它们传递给一组函数 所以我认为这是最好的方法 我想将一个结构传递给未定义该结构的类的构造函数 这可能吗 我的代码看起来像这样 class myClass
  • 在自定义 JsonConverter 的 ReadJson 方法中处理 null 对象

    我有一个 Newtonsoft JSON NETJsonConverter帮助反序列化类型为抽象类的属性 它的要点如下 public class PetConverter JsonConverter public override bool
  • 如果 socket.setdefaulttimeout() 不起作用,我该怎么办?

    我正在编写一个脚本 多线程 来从网站检索内容 并且该网站不是很稳定 所以时不时地会出现挂起的 http 请求 甚至无法超时socket setdefaulttimeout 由于我无法控制该网站 我唯一能做的就是改进我的代码 但我现在没有想法
  • RestKit 和 AFNetworking 构建错误

    当我尝试将 RestKit api 导入项目时 出现以下错误 Documents Code RestTest RestKit Code Network RKHTTPRequestOperation h 21 9 AFNetworking h
  • 连接 Pandas 日期时间

    我有这个问题的解决方案 实际上有两个解决方案 但我对它们不满意 原因是我尝试读取的文件大约有 1200 万行 使用这些解决方案需要花费大量时间来处理它们 主要是因为解法是逐行运算 所以 我读了这样的文件 In 1 df pd read cs
  • 如何使用 Injector 在函数中模拟注入服务

    在 Angular 7 x 中 我有一个全局错误处理 可以使用注入器注入他的服务 因此每个函数都有一个对注入器的引用 如下所示 import ErrorHandler Injectable Injector NgZone from angu