Пересмешивающие зависимости со службами, приводящие к ошибке Firebase - PullRequest
0 голосов
/ 18 декабря 2018

Я использую следующий код для макетирования зависимости с помощью authservice :

login.component.spec

import { LoginComponent } from "./login.component";
import { ComponentFixture, inject, TestBed } from "@angular/core/testing";
import { async } from "q";
import { MatCardModule } from "@angular/material";
import { AuthService } from "../../services/auth/auth.service";
import { Log } from "@angular/core/testing/src/logger";
import { NO_ERRORS_SCHEMA } from "@angular/core";

class MockAuthService extends AuthService {
  isAuthenticated() {
    return "Mocked";
  }
}

describe("LoginComponent", () => {
  let component: LoginComponent;
  let fixture: ComponentFixture<LoginComponent>;
  let componentService: AuthService;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [LoginComponent],
      providers: [AuthService],
      imports: [MatCardModule]
    });
    TestBed.overrideComponent(LoginComponent, {
      set: { providers: [{ provide: AuthService, useClass: MockAuthService }] }
    });

    fixture = TestBed.createComponent(LoginComponent);
    component = fixture.componentInstance;
    componentService = fixture.debugElement.injector.get(AuthService);
  }));

  it("Service injected via component should be and instance of MockAuthService", () => {
    expect(componentService instanceof MockAuthService).toBeTruthy();
  });
});

login.component

import {Component, OnInit} from '@angular/core';

import {AuthService} from '../../services/auth/auth.service';
import {Router} from '@angular/router';
import {GithubService} from '../../services/github/github.service';
import {Errorcode} from './errorcode.enum';


@Component({
  selector: 'app-login',
  templateUrl: './login.component.html',
  styleUrls: ['./login.component.sass'],

})
export class LoginComponent implements OnInit {
  public loginError: string | boolean = false;

  constructor(public authService: AuthService, public router: Router, private data: GithubService) {
  }

  public signInWithGithub(): void {
    this.authService.loginwithGithubProvider()
      .then(this.loginError = null)
      .catch(err => {
        if (err === Errorcode.FIREBASE_POPUP_CLOSED) {
        this.loginError = 'The popup has been closed before authentication';
        }
        if (err === Errorcode.FIREBASE_REQUEST_EXESS) {
          this.loginError = 'To many requests to the server';
        }
      }
    );
  }

  public logout(): void {
    this.authService.logout();
  }

  ngOnInit() {
  }
}

Но если я посмотрю на результаты, я получу следующую ошибку:

Ошибка: StaticInjectorError (DynamicTestModule) [AuthService-> AngularFireAuth]: StaticInjectorError (Платформа: ядро) [AuthService -> AngularFireAuth]: NullInjectorError: Нет поставщика для AngularFireAuth!в http://localhost:9876/_karma_webpack_/vendor.js (строка 59376)

Есть идеи, как мне решить эту проблему?

1 Ответ

0 голосов
/ 18 декабря 2018

Я воспроизвел вашу проблему в Stackblitz .В Stackblitz в настоящее время все тесты проходят, но вы заметите, что я прокомментировал ваше объявление MockAuthService следующим образом:

// class MockAuthService extends AuthService {
//     isAuthenticated() {
//       return "Mocked";
//     }
// }

и заменил его на:

class MockAuthService implements Partial<AuthService> {
    isAuthenticated() {
      return "Mocked";
    }
    loginwithGithubProvider() {
      return new Promise((resolve, reject) => resolve())
    }
    logout() {}
}

Ключразница в том, что я заменил extends на implements.

Чтобы воспроизвести вашу ошибку, просто закомментируйте мою новую декларацию MockAuthService и раскомментируйте вашу оригинальную.Ошибка, которую вы описали выше, появится снова.

Причина этого заключается в том, что при расширении класса вы получаете все объекты, свойства, методы и т. Д. Существующего класса , включая конструктор .В вашем случае я вполне уверен, что конструктор для исходного класса AuthService внедрил AngularFireAuth, как я это делал в Stackblitz в файле support.service.ts, где я реализовал заглушку AuthService.Когда вы расширили класс и затем внедрили его в TestBed, когда вы переопределили компонент, а затем попытались создать компонент, он попытался выполнить конструктор в этом исходном классе.Однако для AngularFireAuth не было предоставлено ни одного поставщика, поэтому он выдает ошибку, которую вы видите.Простое добавление AngularFireAuth к массиву провайдеров не было бы правильным решением, потому что вы пытаетесь протестировать компонент, а не сервис.

Когда я хочу внедрить фиктивный класс в набор тестов, как вы это сделализдесь я обычно использую implements, а затем Partial<>, чтобы мне не нужно было реализовывать все методы и свойства исходного класса, и чтобы я только издевался над тем, что хочу, а не тащил вдоль исходного классадетали реализации.

Здесь довольно неплохо обсуждаются различия между implements и extends .

Некоторые дополнительные примечания:

  • Мне пришлось добавить две другие поддельные службы для Router и GithubService.Обратите внимание, что я делал это как шпионы, а не как имитация класса обслуживания, просто чтобы показать другой способ сделать это.Я заметил, что вы импортировали NO_ERRORS_SCHEMA, вероятно, чтобы избежать их определения.Я сам не использую эту схему, хотя она кажется довольно популярной, поскольку я не хочу маскировать ошибки - я бы предпочел, чтобы они были раскрыты и исправлены.:)
  • Я также добавил еще одну спецификацию, чтобы показать, как можно сделать следующий шаг, протестировав часть метода signInWithGithub().

Надеюсь, это поможет.

...