Поддельный сервис в компоненте все еще требует HttpClient как провайдер - PullRequest
0 голосов
/ 28 января 2019

У меня есть компонент, который использует mockService.Я создал как таковой.

ПРИМЕЧАНИЕ. Для этого вопроса я изменил имя, в проекте у него есть более конкретное имя.

list.component.spec.ts

describe('ListComponent', () => {
  let component: ListComponent;
  let fixture: ComponentFixture<ListComponent>;
  let ITEMS: ListItem[];
  let mockService;

  beforeEach(async(() => {
    ITEMS = require('../../../../../assets/mockdata/items.json');
    mockService = jasmine.createSpyObj(['getItems']);

    TestBed.configureTestingModule({
      imports: [NoopAnimationsModule, RouterTestingModule, SharedModule],
      declarations: [ListComponent, SomePipe, AnotherPipe],
      providers: [
        {
          provide: Service,
          useValue: mockService,
        },
      ],
    }).compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(TimesheetListComponent);
    component = fixture.componentInstance;
    mockService.getItems.and.returnValue(of(ITEMS));
    fixture.detectChanges();
  });

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

list.component.ts

@Component({
  selector: 'app-list',
  templateUrl: './list.component.html',
  styleUrls: ['./list.component.scss'],
})
export class ListComponent implements OnInit {
  // left out props;

  constructor(private service: Service, private router: Router, private route: ActivatedRoute) {
    // This forces the page to reload to the default queryparams when no queryparams are given.
    this.router.routeReuseStrategy.shouldReuseRoute = function() {
      return false;
    };
  }

Это приводит к следующей ошибке:

Error: StaticInjectorError(DynamicTestModule)[Service -> HttpClient]:
          StaticInjectorError(Platform: core)[Service -> HttpClient]:
            NullInjectorError: No provider for HttpClient!

У меня совершенно другой компонент(DetailComponent) также использует этот Service, но он ни на что не жалуется.

Я не должен предоставлять HttpClient, потому что list.component.ts не имеет зависимости от этого компонента, служба имеет это, и я тестировал этот код отдельно.

Я действительно сбит с толку,может я что то смотрю или?Любая помощь очень ценится.

1 Ответ

0 голосов
/ 28 января 2019

Эта проблема может возникнуть при тестировании компонента, который создает экземпляр дочернего компонента, который также внедряет службу, используя HttpClient.

Для иллюстрации рассмотрим следующие компоненты:

@Component({
  selector: 'app-parent-component',
  template: `<app-child-component></app-child-component>`
})
export class ParentComponent {
  constructor(private service: FooService) { }
}

@Component({
  selector: 'app-child-component',
})
export class ChildComponent {
  constructor(private service: BarService) { }
}

Предположимчто и FooService, и BarService вводят HttpClient.

В соответствии с документацией тест, настроенный для ParentComponent, может выглядеть примерно так:

beforeEach(async(() => {
  const mockService = jasmine.createSpyObject(['fooMethod']);
  TestBed.configureTestingModule({
    declarations: [ParentComponent],
    providers: [
      {
        provide: FooService,
        useValue: mockService,
      },
    ],
  }).compileComponents();
}));

Однако, когда angular создает экземпляр ParentComponent, а также создает ChildComponent, который должен ввести BarService.Так как вы не сказали TestBed предоставить макет, он предоставляет реальную услугу, которая, в свою очередь, зависит от HttpClient.

Существует несколько решений.Если вы хотите проверить интеграцию ParentComponent и ChildComponent, самое простое, что вам нужно сделать - это сказать TestBed, чтобы высмеивать BarService, требуемый ребенком.Если вы хотите поддерживать строгий модульный тест, вы можете предоставить поддельный дочерний компонент, который не внедряет службу HttpClient в TestBed:

@Component {(
  selector: 'app-child-component'
)}
export class MockChildComponent {
  constructor() { }
}

, и настроить тест следующим образом:

TestBed.configureTestingModule({
  declarations: [ParentComponent, ChildComponent],
  providers: [
    {
      provide: Service,
      useValue: mockService,
    },
  ],
}).compileComponents();

Или вы можете переопределить создание экземпляра компонента, сказав TestBed использовать CUSTOM_ELEMENTS_SCHEMA:

TestBed.configureTestingModule({
  declarations: [ParentComponent],
  providers: [
    {
      provide: Service,
      useValue: mockService,
    },
  ],
  schemas: [CUSTOM_ELEMENTS_SCHEMA]
}).compileComponents();
...