使用 DI 进行单元测试和模拟服务

2024-06-23

我已经为此苦苦挣扎了一段时间,希望有人能提供帮助。我有一个使用服务来获取数据的组件。我正在尝试向其添加单元测试。我的问题是测试总是失败并显示“错误:没有 Http 提供程序”。这是我的代码:

Service:

import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import { Observable } from 'rxjs/Rx';
import 'rxjs/add/operator/map';

import { Contact } from './contact.model';

@Injectable()
export class ContactsService {
    constructor(private http: Http) { }

    public getContacts(): Observable<Array<Contact>> {
        return this.http.get('assets/contacts.json').map(res => {
            let r = res.json().Contacts;
            return r;
        });
    }
}

成分:

import { Component, OnInit, NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { Contact } from '../contact.model'; 
import { ContactsService } from '../contacts.service';

@Component({
    selector: 'app-contacts',
    templateUrl: './contacts.component.html',
    styleUrls: ['./contacts.component.css'],
    providers: [ContactsService]
})
export class ContactsComponent implements OnInit {

    contactsAll: Array<Contact>;
    contacts: Array<Contact>;

    constructor(private contactsService: ContactsService) { }

    ngOnInit() {
        this.contactsService.getContacts().subscribe((x) => {
            this.contactsAll = x;
            this.contacts = this.contactsAll;
        });
    }

}

Tests:

import { async, ComponentFixture, TestBed, inject } from '@angular/core/testing';
import { FormsModule } from '@angular/forms';
import { By } from '@angular/platform-browser';
import { Observable } from 'rxjs/Rx';

import { ContactsComponent } from './contacts.component';
import { ContactsService } from '../contacts.service';
import { Contact } from '../contact.model';

class MockContactsService extends ContactsService {

    constructor() {
        super(null);
    }

    testContacts: Array<Contact> = [
        new Contact("test1 mock", 12345, 10000),
        new Contact("test2 mock", 23456, 20000)
    ];

    public getContacts(): Observable<Array<Contact>> {
        return Observable.of(this.testContacts);
    }
}

describe('ContactsComponent', () => {
    let component: ContactsComponent;
    let fixture: ComponentFixture<ContactsComponent>;

    beforeEach(async(() => {
        TestBed.configureTestingModule({
            imports: [FormsModule],
            declarations: [ContactsComponent],
           // providers: [{ provide: ContactsService, useClass: MockContactsService }] // this is needed for the service mock
        }).overrideComponent(ContactsService, {// The following is to override the provider in the @Component(...) metadata
            set: {
                providers: [
                    { provide: ContactsService, useClass: MockContactsService },
                ]
            }
        }).compileComponents();
    }));

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

    it('should create', () => {
        expect(component).toBeTruthy();
    });

    describe('1st test', () => {
        it('true is true', () => expect(true).toBe(true));
    })
});

让我们试试这个:

首先,将提供程序数组从组件移动到 NgModule。最好在模块级别提供服务,因为它将您的提供者与组件树结构解耦(除非您特别希望每个组件都有一个单独的提供程序实例,并且从您的简化用例来看,不需要每个组件有一个单独的实例)。

so,

@Component({
    selector: 'app-contacts',
    templateUrl: './contacts.component.html',
    styleUrls: ['./contacts.component.css'],
   /// providers: [ContactsService]  <-- remove this line
})
export class ContactsComponent implements OnInit {
   .....

并将其添加到声明您的 ContactsComponent 的 NgModule 中

 @NgModule({
    imports: ..
    declarations: ...
    providers: [ContactsService] // <-- provider definition moved to here
 })
 export class ModuleDeclaringContactsComponent

一旦你这样做了,那么在你的测试中模拟 ContactsService 就很容易实现。

TestBed.configureTestingModule({
        imports: [FormsModule],
        declarations: [ContactsComponent],
        providers: [{ provide: ContactsService, useClass: MockContactsService }] // this is needed for the service mock
    });

这样,您就可以开始了。

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

使用 DI 进行单元测试和模拟服务 的相关文章

随机推荐

  • NodeJS、Mongoose:如何使用 mongoose 获取相关数据

    我有 2 个集合 它们是一对多的关系 如何使用猫鼬获取相关数据作为嵌套文档 我有 2 个模式 它们是这样相关的 var userSchema mongoose Schema name String age Number var postSc
  • 在 Bootstrap 3 的折叠导航栏中显示图标

    我想构建一个像 facebook 应用程序一样的 bootstrap 3 导航栏 带有一些图标 问题是 当栏折叠时 所有图标都会隐藏 如果我把图标放在外面 div class collapse navbar collapse 图标出来了并且
  • 我的 tomcat 启动时出现 C3P0 明显死锁

    当我通过tomcat或resin启动我的项目时 我的项目将抛出错误 APPARENT DEADLOCK 我认为c3p0引起的错误无法连接我的数据库 我更改了我的xml并将域名替换为我数据库的ip 然后项目启动了 我在c3p0工作之前使用了监
  • Woocommerce REST API 扩展订单响应

    我正在寻找一种扩展 wc api vX orders 响应的方法 我在结帐中添加了多个自定义字段 例如 关系编号 交货日期等 这些元数据保存在订单中 wp postmeta 表 但为什么他们不随 api 返回呢 通常 您可以使用以下代码扩展
  • 强制mapply返回列表?

    假设我有一个创建数据框的函数 我想使用不同的输入值运行该函数 然后将结果绑定到一个大数据框中 如下所示 CreateDataFrame lt function type A n 10 n true 8 data frame success
  • 如何显示在 Rails 控制台中运行的 SQL 查询?

    当我运行查询时 例如MyModel where or record associated things 在控制台中 如何查看正在运行的实际数据库查询 以便更好地了解正在发生的情况 Rails 3 在控制台中输入这一行 ActiveRecor
  • 在Python中使用networkX包绘制图形分区

    我有一个图形对象G节点来自0 to n 1和两个列表L1 L2这是节点的一个分区G 我想画画G以这样一种方式 节点结果分为两个块 一个相对于L1另一个相对于L2 图片的目的应该是证明之间的联系L1 and L2 你能帮我完成这个任务吗 提前
  • 如何使用 php Restful 以 api 为中心的内部设计而不是使用 http 请求

    我想创建一个以 php Restful api 为中心的 Web 应用程序 网站 其中有从前端代码调用的数据 api 除了每次加载页面时进行 HTTP curl 请求调用之外 使用 slim 等框架进行内部 API 调用还能做什么 我不确定
  • 是否可以在 Outlook 启动时运行 VBA 函数?

    我希望 Outlook 启动后立即运行 VBA 函数 这可能吗 如果可以 我需要做什么 我在谷歌上的搜索失败了 我不介意弹出安全警报 Use the Application Startup事件在ThisOutlookSession Priv
  • 序列化一个空类(没有字段)

    我有以下课程 class Foo JsonCreator public Foo 我得到以下异常 com fasterxml jackson databind JsonMappingException 没有找到类 Foo 的序列化器 也没有发
  • System.Net.Http.MultipartFormDataContent 的“curl -F”参数等效吗?

    我正在尝试使用sonicAPI 文件 上传 API https www sonicapi com docs api file upload in C 我尝试将 curl 示例转换为 C HttpClient and MultipartFor
  • 如何以编程方式制作 UIImage?

    这可能不是您一开始所想的 我知道如何使用 UIImage 但我现在需要知道如何使用以下方法创建 空白 UIImage CGRect screenRect self view bounds 嗯 这些尺寸 不管怎样 我想知道如何创建一个 UII
  • 使用 asp.net 身份在 Web api 中启用两因素身份验证时,SignInStatus 始终返回成功

    我正在 WebApi asp net 身份和 OWIN 中实现 2 因素身份验证 每次登录时 我都会收到 SignInStatus Success 但从未达到 SignInStatus RequiresVerification 尽管启用了用
  • 可以访问 JSF/facelets 中的请求参数的过滤器会导致错误的编码

    我面临以下问题 错误 对于用例 我添加了一个 log4j 过滤器 因为它可以提供很好的日志记录 请参阅here https stackoverflow com questions 5901347 a unique id per user s
  • 可点击的链接未出现在生成的锚标记的页面上

    我有一些 js 代码生成以下锚标记 a 2017 09 10 a 我从 IE 的 DOM Explorer 中剪切并粘贴了它 该链接在我显示的页面上不可单击 这是我希望它运行的 vb net Sub DownloadInspection C
  • 关于存储库模式的一些我根本不明白的事情

    我已经阅读了很多关于存储库是什么的主题 但仍然有一些事情困扰着我 据我了解 两者之间唯一的区别存储库 and 传统数据访问层 are 存储库的查询构造能力 即查询对象模式 但是当阅读以下 a 的定义时存储库模式 看来我们还可以有存储库即使我
  • 网页导航

    我正在寻找有关如何为基于 Spring 的 Web 应用程序最好地实现网页导航逻辑的指南 例如 我有一个网页 C 如果单击 确定 我希望流程返回到页面 A 如果这是上一页 或者页面 B 如果这是上一页 我目前正在页面上使用隐藏字段来跟踪我到
  • Swift 中的函数签名专业化崩溃

    我从用户那里收到崩溃报告 但我不明白该崩溃报告 It says Ribony function signature specialization
  • 将信息打印到shiny-server日志中

    有没有办法将信息包含 打印到闪亮的服务器日志文件中 我正在使用一个闪亮的应用程序 其中包括用户登录 如果我的应用程序崩溃 我想知道是什么用户导致了这次崩溃 我试图将其纳入我的server R PRINT FOR LOG FILE cat p
  • 使用 DI 进行单元测试和模拟服务

    我已经为此苦苦挣扎了一段时间 希望有人能提供帮助 我有一个使用服务来获取数据的组件 我正在尝试向其添加单元测试 我的问题是测试总是失败并显示 错误 没有 Http 提供程序 这是我的代码 Service import Injectable