Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mocking service in a component - mock ignored

This time I'm trying to mock a service (that does http calls) to test a component.

@Component({
  selector: 'ub-funding-plan',
  templateUrl: './funding-plan.component.html',
  styleUrls: ['./funding-plan.component.css'],
  providers: [FundingPlanService]
})
export class FundingPlanComponent implements OnInit {
  constructor(private fundingPlanService: FundingPlanService) {
  }

  ngOnInit() {
    this.reloadFundingPlans();
  }

  reloadFundingPlans() {
    this.fundingPlanService.getFundingPlans().subscribe((fundingPlans: FundingPlan[]) => {
      this.fundingPlans = fundingPlans;
    }, (error) => {
      console.log(error);
    });
  }
}

The documentation (version 2.0.0) explains that you should mock the service. Using the same TestBed configuration:

describe('Component: FundingPlan', () => {
  class FundingPlanServiceMock {
    getFundingPlans(): Observable<FundingPlan> { return Observable.of(testFundingPlans) }
  }

  beforeEach(() => {
    TestBed.configureTestingModule({
      declarations: [FundingPlanComponent],
      providers: [
        { provide: FundingPlanService, useClass: FundingPlanServiceMock },
      ]
    });

    fixture = TestBed.createComponent(FundingPlanComponent);
    component = fixture.componentInstance;
  });

  fit('should display a title', () => {
    fixture.detectChanges();
    expect(titleElement.nativeElement.textContent).toContain('Funding Plans');
  });

});

When I run the test, I get:

Error: No provider for AuthHttp!

that is indeedused by the actual service, but not by the mock. So for some reason, the mock is not injected or used.

Any advise? Thanks!

like image 852
youri Avatar asked Oct 13 '16 12:10

youri


1 Answers

It's because of

@Component({
  providers: [FundingPlanService] <===
})

The @Component.providers takes precedence over any global providers, since using the @Component.providers makes the provider scoped only to the component. In the test, Angular creates the mocked service in the module scope and the original service in the component scope.

To solve this problem, Angular provides the TestBed.overrideComponent method, where we can override things like templates and providers at the component level.

TestBed.configureTestingModule({
  declarations: [FundingPlanComponent]
});
TestBed.overrideComponent(FundingPlanComponent, {
  set: {
    providers: [
      { provide: FundingPlanService, useClass: FundingPlanServiceMock },
    ]
  }
})

See also:

  • Override a component's providers - Angular Testing Docs
like image 78
Paul Samsotha Avatar answered Oct 23 '22 19:10

Paul Samsotha