【问题标题】:Why isn't my test using the service stub method?为什么我的测试不使用服务存根方法?
【发布时间】:2017-03-22 17:15:30
【问题描述】:

我有这个规格:

import {TestBed, ComponentFixture} from '@angular/core/testing';
import { LoginComponent } from './login.component';
import {UserService} from "../services/user.service";
import {HttpModule} from "@angular/http";
import {FormsModule} from "@angular/forms";
import {RouterTestingModule} from "@angular/router/testing";

describe('LoginComponent', () => {

  let component: LoginComponent;
  let service: UserService;
  let fixture: ComponentFixture<LoginComponent>;



  class UserServiceStub {
    userLogin(email: string, password: string) {
      return [email, password];
    }
  }


  beforeEach(() => {

    TestBed.configureTestingModule({
      declarations: [LoginComponent],
      imports: [HttpModule, FormsModule, RouterTestingModule],
      providers: [
        {provide: UserService, useClass: UserServiceStub}
      ]
    });

    service = TestBed.get(UserService);
    fixture = TestBed.createComponent(LoginComponent);
    component = fixture.componentInstance;

  });





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

  it('should call the service when the sign in button is clicked', () => {
    component.onLoginButtonClick();
    expect(service.userLogin("pippo", "pluto")).toBe(["pippo", "pluto"]);

  });
});

我不知道显示的问题是什么:

TypeError: this.userService.userLogin(...).catch is not a function
    at LoginComponent.onLoginButtonClick (http://0.0.0.0:9882/base/src/test.ts:71519:68)
    at Object.<anonymous> (http://0.0.0.0:9882/base/src/test.ts:71485:19)
    at ZoneDelegate.invoke (http://0.0.0.0:9882/base/src/test.ts:108270:26)
    at ProxyZoneSpec.onInvoke (http://0.0.0.0:9882/base/src/test.ts:103404:39)
    at ZoneDelegate.invoke (http://0.0.0.0:9882/base/src/test.ts:108269:32)
    at Zone.run (http://0.0.0.0:9882/base/src/test.ts:108066:43)
    at Object.<anonymous> (http://0.0.0.0:9882/base/src/test.ts:103119:34)
    at attemptSync (http://0.0.0.0:9882/base/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:1950:24)
    at ZoneQueueRunner.QueueRunner.run (http://0.0.0.0:9882/base/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:1938:9)
    at ZoneQueueRunner.QueueRunner.execute (http://0.0.0.0:9882/base/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:1923:10)
    at ZoneQueueRunner.jasmine.QueueRunner.ZoneQueueRunner.execute (http://0.0.0.0:9882/base/src/test.ts:103149:42)
    at Spec.queueRunnerFactory (http://0.0.0.0:9882/base/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:714:35)
    at Spec.execute (http://0.0.0.0:9882/base/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:371:10)
    at Object.fn (http://0.0.0.0:9882/base/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:2579:37)
    at attemptAsync (http://0.0.0.0:9882/base/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:1980:24)

看起来测试是在真实服务上进行的,而不是在 UserServiceStub 上。

【问题讨论】:

    标签: angular testing jasmine karma-runner


    【解决方案1】:

    您观察到的问题是,您的真实服务中的 userLogin 方法正在返回一个 Promise,而您的存根类中的 userLogin 方法正在返回一个数组。由于数组没有catch 方法,因此会导致错误。您要完成的是:

    import {TestBed, ComponentFixture} from '@angular/core/testing';
    import { LoginComponent } from './login.component';
    import {UserService} from "../services/user.service";
    import {HttpModule} from "@angular/http";
    import {FormsModule} from "@angular/forms";
    import {RouterTestingModule} from "@angular/router/testing";
    
    describe('LoginComponent', () => {
    
      let component: LoginComponent;
      let service: UserService;
      let fixture: ComponentFixture<LoginComponent>;
      let userService: UserServiceStub; // NEW
    
    
    
      class UserServiceStub {
        userLogin(email: string, password: string) {
          return Promise.resolve([email, password]); // UPDATED
          // OR: return Observable.of([email, password]);
        }
      }
    
    
      beforeEach(() => {
        userService = new UserServiceStub();
    
        TestBed.configureTestingModule({
          declarations: [LoginComponent],
          imports: [HttpModule, FormsModule, RouterTestingModule],
          providers: [
            {provide: UserService, useValue: userService} // UPDATED
          ]
        });
    
        service = TestBed.get(UserService);
        fixture = TestBed.createComponent(LoginComponent);
        component = fixture.componentInstance;
    
      });
    
    
    
      it('should create', () => {
        expect(component).toBeTruthy();
      });
    
      it('should call the service when the sign in button is clicked', () => {
        spyOn(userService, 'userLogin').and.callThrough(); // NEW
        component.onLoginButtonClick();
        expect(service.userLogin).toHaveBeenCalled(); // UPDATED
      });
    });
    

    您可以阅读更多关于茉莉花间谍here 的信息。要点是它们允许您检查是否已调用方法。您还可以检查调用的内容、返回的内容等。有很多方法可以使用它们,它们非常强大。我希望这会有所帮助!

    【讨论】:

    • 太棒了!我使用 observable.of 而不是 promise.resolve,因为我的服务使用 Observables。非常感谢。
    猜你喜欢
    • 2017-11-10
    • 1970-01-01
    • 1970-01-01
    • 2012-05-06
    • 1970-01-01
    • 1970-01-01
    • 2010-10-11
    • 2018-05-30
    • 2020-09-28
    相关资源
    最近更新 更多