【问题标题】:How to use jasmineSpy to test Angular component?如何使用 jasmineSpy 测试 Angular 组件?
【发布时间】:2019-01-21 23:55:22
【问题描述】:

我有如下组件和服务。我想编写一个单元测试来测试这个组件,尝试使用 Spy 来模拟服务,但是它在启动组件时抛出“没有 HttpClient 提供者”错误,因为我的 NewsService 依赖于 HttpClient。

我应该如何调整我的代码来注入 HttpClient?

主页组件:

import { Component,Inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { HttpHeaders } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import { Router } from '@angular/router';
import { News } from '../models/news';
import { NewsService } from '../service/news.service';

@Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.css'],
providers: [NewsService]
})
export class HomeComponent {
public news: News[];
public headline: News;
private baseUrl: string;
constructor(private router: Router, private service: NewsService) {

}
ngOnInit() {
  let baseUrl = document.getElementsByTagName('base')[0].href;
  var headurl = this.baseUrl + "api/News/Headline?country=us&category=business";
  this.service.getNews(headurl).subscribe((res) => { this.headline = res[0]; });

  var url = this.baseUrl + "api/News/Category?country=us&category=business";

  this.service.getNews(url).subscribe((res) => this.news = res);

}

新闻服务

import { Injectable } from '@angular/core';
import { HttpClient, HttpParams } from '@angular/common/http';
import { HttpHeaders } from '@angular/common/http';
import { News } from '../models/news';
import { Observable } from 'rxjs';

const httpOptions = {
headers: new HttpHeaders({
'Content-Type':  'application/json'
})
};

@Injectable()
export class NewsService {
constructor(
private http: HttpClient) {
}

getNews(url:string): Observable<News[]> {
  return this.http.get<News[]>(url);
  }

}

测试

import { async, fakeAsync, ComponentFixture, TestBed, tick } from '@angular/core/testing';
import { HttpClient, HttpResponse } from '@angular/common/http';
import { News } from '../models/news';
import { NewsService } from '../service/news.service';
import { HomeComponent } from '../home/home.component';
import { of } from 'rxjs/observable/of';import { Router } from '@angular/router';

describe('HomeComponent', () => {
        let component: HomeComponent;
        let fixture: ComponentFixture < HomeComponent > ;
        let getNewsSpy: jasmine.Spy;
        let headlineEl: HTMLElement;
        let testheadline: News[];
        let url: string;

        beforeEach(() => {
            testheadline = [{
                NewsId: 'test',
                author: 'test',
                description: 'headline',
                publishedAt: '2018-8-8',
                title: 'Android ',
                url: 'http://www.ghostchina.com',
                urlToImage: 'http://static.ghostchina.com/image/c/06/765c76cb1ca259dd8fe8002459bbc.jpg'
            }] as News[];

            const newsService = jasmine.createSpyObj('NewsService', ['getNews']);
            let url = 'api/News/Headline?country=us&category=business';
            getNewsSpy = newsService.getNews.and.returnValue( of (testheadline));
            const routerSpy = jasmine.createSpyObj('Router', ['navigate']);

            TestBed.configureTestingModule({
                declarations: [HomeComponent],
                providers: [{
                    provide: NewsService,
                    useValue: newsService
                }, {
                    provide: Router,
                    useValue: routerSpy
                }]
            });
            fixture = TestBed.createComponent(HomeComponent);
            component = fixture.componentInstance;
        });

        describe('#oninit', () => {
                    it('should return expected category news (called once)', () => {
                                let url = 'api/News/Category?country=us&category=business';
                                fixture.detectChanges(); // onInit()  
                                expect(getNewsSpy.calls.any()).toBe(false, 'getNews not yet called');         });  });

【问题讨论】:

    标签: angular jasmine angular-services angular-components


    【解决方案1】:

    因此您会收到错误消息。

    @Component({
        providers: [NewsService]
    })
    

    当我们使用@component.providers组件级别 提供服务时。它优先于任何全局提供程序,这使得提供程序仅作用于组件

    因此,没有必要为测试模块提供存根服务。(因为您有组件级服务。)

    您需要做的是向组件提供服务存根。为此,您可以使用TestBed.overrideComponent 方法。使用它,我们可以覆盖组件的模板和提供程序。

     const newsService = jasmine.createSpyObj('NewsService', ['getNews']);
    
     TestBed.configureTestingModule({
       declarations: [HomeComponent]
     });
    
     TestBed.overrideComponent(HomeComponent, {
       set: {
        providers: [
                    {provide: NewsService,useValue: newsService}
        ]
      }
    })
    

    您可以在Angular Testing Docs

    中阅读更多关于覆盖组件的提供者

    【讨论】:

      猜你喜欢
      • 2020-09-04
      • 1970-01-01
      • 1970-01-01
      • 2020-12-22
      • 1970-01-01
      • 2022-01-15
      • 2017-06-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多