Angular 7 Component Test使用的是原始服务而不是模拟 [英] Angular 7 Component Test is using original service instead of mock

查看:67
本文介绍了Angular 7 Component Test使用的是原始服务而不是模拟的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试测试具有注入服务的组件.我想在测试中提供模拟服务.但是,测试使用的是原始服务而不是模拟服务(我知道这一点,因为我收到"No Client for HttpClient!"错误,并且在测试中输出的原始服务中也有console.log).

I am trying to test a component that has an injected service. I want to provide a mock service in my test. However the test is using the original service instead of the mock one (I know this because I am getting a "No provider for HttpClient!" error and also I have a console.log in the original service that is outputting in the test).

我可以通过导入HttpClientTestingModule来修复错误,但这不能解决使用原始服务而不是模拟服务这一事实.

I can fix the error by importing the HttpClientTestingModule but this doesn't fix the fact that the original service is being used instead of the mock one.

有任何想法我在做什么错吗?

Any ideas what I am doing wrong?

这是我的测试代码. Angular版本7

Here is my test code. Angular version 7

import { TestBed, async, ComponentFixture } from '@angular/core/testing';
import { HelloWorldComponent } from '../../app/components/hello-world/hello-world.component';
import { HelloWorldService } from '../../app/services/hello-world.service';

describe('HelloWorldComponent', () => {

  let component: HelloWorldComponent;
  let fixture: ComponentFixture<HelloWorldComponent>;
  let mockHelloWorldService;
  
  beforeEach(() => {

    mockHelloWorldService = jasmine.createSpyObj(['getHelloWorld']);
    
    TestBed.configureTestingModule({
      imports: [],
      declarations: [HelloWorldComponent],
      providers: [
        [{ provide: HelloWorldService, useClass: mockHelloWorldService }]
      ]
    }).compileComponents();

    fixture = TestBed.createComponent(HelloWorldComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
	
  });

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

更新

我尝试了overrideProvider,现在遇到了无法读取未定义的属性'subscribe'(未定义)"错误,感觉像是进度...

I have tried overrideProvider and now I am now getting a 'Cannot read property 'subscribe' of undefined' error, which sort of feels like progress...

这是我的测试代码

import { TestBed, async, ComponentFixture } from '@angular/core/testing';
import { HelloWorldComponent } from '../../app/components/hello-world/hello-world.component';
import { HelloWorldService } from '../../app/services/hello-world.service';
import { of } from 'rxjs';

describe('HelloWorldComponent', () => {

  let component: HelloWorldComponent;
  let fixture: ComponentFixture<HelloWorldComponent>;
  let mockHelloWorldService;

  beforeEach(async(() => {
    mockHelloWorldService = jasmine.createSpyObj(['getHelloWorld']);
    TestBed.configureTestingModule({
      imports: [],
      declarations: [HelloWorldComponent]
    });
    TestBed.overrideProvider(HelloWorldService, { useValue: mockHelloWorldService });
    TestBed.compileComponents();

  }));

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

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

这是我的组成部分

import { Component, OnInit } from '@angular/core';
import { HelloWorldService } from '../../services/hello-world.service';

@Component({
  selector: 'app-hello-world',
  templateUrl: './hello-world.component.html',
  providers: [HelloWorldService]
})
export class HelloWorldComponent implements OnInit {

  helloWorldMessage: any;
  constructor(private helloWorldService: HelloWorldService) { }

  ngOnInit() {
    this.getHelloWorldMsg();
  }

  getHelloWorldMsg() {
    this.helloWorldService
      .getHelloWorld()
      .subscribe((data) => {
        this.helloWorldMessage = data;
        }, err => this.handleErrorResponse('There was a problem loading the hello world message', err));
  }

  handleErrorResponse(errorMsg: string, error?: any) {
    console.log("There was a problem getting the message");
  }
}

这是我的服务

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

import { environment } from '../../environments/environment';

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

  getHelloWorld(): Observable<any> {
    console.log("Why is the test coming here when I provide a mock?");
    var getHelloWorldApiUrl = environment.apiUrl + "/api/v1.0/helloworld/GetHelloWorldMessageAuth";
    return this.http
    .get(getHelloWorldApiUrl);
  }
}

推荐答案

我在上面的代码中看到了两个问题:

I see two issues in the code above:

  • 您的TestBed的provider数组中有一组额外的方括号.我认为这不是主要问题,从语义上讲是不正确的.
  • 在providers数组中提供HelloWorldService时,已指定了useClass,但提供了一个对象(jasmine.createSpyObj()产生的对象),因此应改为指定useValue.
  • You have an extra set of square brackets in the providers array of your TestBed. I don't think this is a major issue, it is just semantically incorrect.
  • When you provide HelloWorldService in the providers array, you have specified useClass, but have provided an object (which is what jasmine.createSpyObj() produces), so you should instead specify useValue.

我希望这会有所帮助.

好的,您已经走了很长一段路!您已纠正了我上面概述的两个问题,正如我在对另一个答案的评论中所建议的那样,已经在compileComponents()之前完成了overrideProvider(),并将beforeEach()包裹在了async()内.

Ok, you have come quite a long ways! You corrected the two problems I outlined above, have done the overrideProvider() before the compileComponents() as I suggested in a comment to another answer as well as wrapped the beforeEach() inside an async().

我要求查看所有其他代码的原因是,我可以将其快速放入以下 StackBlitz 进行测试.如您在StackBlitz中看到的那样,测试现在通过了.

The reason I asked to see all the other code was so I could quickly put it up in the following StackBlitz for testing. As you can see in that StackBlitz, the test is now passing.

我只在beforeEach()中添加了一行以从您的间谍中声明returnValue,以便您组件中的订阅具有一个Observable来订阅:

I only added one line in the beforeEach() to declare a returnValue from your spy, so that the subscribe in your component has an Observable to subscribe to:

mockHelloWorldService.getHelloWorld.and.returnValue(of('Test Message'));

我在调用fixture.detectChanges()之前添加了此选项,因为它将调用ngOnInit(),并且间谍在执行ngOnInit()之前需要设置返回值,以便它可以正确执行,并且不会给您看到的错误.

I added this before the call to fixture.detectChanges() since this will invoke ngOnInit(), and the spy needs a return value set BEFORE executing ngOnInit() so that it will execute correctly and not give you the error you were seeing.

我还在规范中添加了一行,以说明如何测试Observable的结果是否正确设置为组件变量:

I also added a line in the spec to show how you can test that the result of the Observable is correctly set to your component variable:

expect(component.helloWorldMessage).toEqual('Test Message');

请注意,通过在组件声明的providers数组中指定HelloWorldService,将使测试复杂化.相反,如果您以root身份作为单例提供此服务,则可以简化很多事情,包括如何进行测试.在官方文档中查看详细信息.

Note that you are significantly complicating your testing by specifying the HelloWorldService in the providers array of your component declaration. If you instead provide this service as a singleton in root that will simplify things a lot, including how you test. See details in the Official Docs.

这篇关于Angular 7 Component Test使用的是原始服务而不是模拟的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆