Solvedangular Provide a mock service using TestBed

I'm submitting a ... (check one with "x")

[ x] bug report

Current behavior
TestBed providers looks for the dependencies of my original service although my mocked service have none of them.
And sometimes when running the test I get:
This test module uses the component DummyRestApiComponent which is using a "templateUrl", but they were never compiled. Please call "TestBed.compileComponents" before your test.
Although I am calling TestBed.compileComponents.

Expected/desired behavior
Before RC5 addProviders used the mock without looking for its dependencies which reduces the knowledge the component in test knows about the service.

Reproduction of the problem

      declarations: [DummyRestApiComponent],
      providers: [
        // ConfigurationService,
        {provide: DummyRestApiService, useClass: MockDummyRestApiTestService},
      imports: [FormsModule, HttpModule]

Vs The old way

       {provide: DummyRestApiService, useClass: MockDummyRestApiTestService},

No need for configuration Service.

Before each test I am using

 beforeEach(async(() => {
      TestBed.compileComponents().catch(error => console.error(error));

And when testing

 it('should create an instance', async(() => {
        var fixture = TestBed.createComponent(DummyRestApiComponent);
  • Angular version: 2.0.0-rc.5

Using Karma + Jasmine (Angular CLI 1.0.0-beta.10)

  • Language: [Typescript]
39 Answers

✔️Accepted Answer

I was having this issue as well, however I noticed that my @component metadata still had the providers array defined. Moving this providers array into my applications @NgModule solved this issue for me.

From what I've seen so far, there is no way to override (mock) a provider specified in a @component metadata.

Other Answers:

@timshelley From what I understand, declaring providers on the component level is still supported and useful, so moving them to the module level seems like changing your implementation just to make the test work, which I didn't want to do. This works for me with rc.6:

TestBed.overrideComponent(MyComponent, {
  set: {
    providers: [{ provide: SomeService, useValue: myMock }]

With the current state of documentation around testing, it is a really frustrating exercise to come up with decent solutions for non-trivial cases. I hope this changes soon.

Using overrideComponent worked for me (I had called it wrong), but setting the providers with TestBed.configureTestingModule is broken.

Here is the code for clarity: -

      imports: [FormsModule, HttpModule],
      declarations: [LoginComponent],
    }).overrideComponent(LoginComponent, {
      set: {
        providers: [
          {provide: AuthenticationService, useValue: authServiceMock},
          {provide: Router, useValue: routerStub}

Thanks for the tip @chris-jones-pixitmedia

I can confirm that I was able to mock a service with TestBed as well. Here's a code snippet:

describe('Component: Search', () => {
  let mockSearchService: MockSearchService;
  let mockActivatedRoute: MockActivatedRoute;
  let mockRouter: MockRouter;

  beforeEach(() => {
    mockSearchService = new MockSearchService();
    mockActivatedRoute = new MockActivatedRoute({'term': 'peyton'});
    mockRouter = new MockRouter();

      declarations: [SearchComponent],
      providers: [
        {provide: SearchService, useValue: mockSearchService},
        {provide: ActivatedRoute, useValue: mockActivatedRoute},
        {provide: Router, useValue: mockRouter}
      imports: [FormsModule]

I've also used useClass with success:

beforeEach(() => {

    providers: [
        provide: Http, useFactory: (backend: ConnectionBackend, defaultOptions: BaseRequestOptions) => {
        return new Http(backend, defaultOptions);
      }, deps: [MockBackend, BaseRequestOptions]
      {provide: SearchService, useClass: SearchService},
      {provide: MockBackend, useClass: MockBackend},
      {provide: BaseRequestOptions, useClass: BaseRequestOptions}

I wrote up a tutorial on using the new testing infrastructure in RC5 since there doesn't seem to be much documentation available.

@AshMcConnell I don't think it's broken. If you declare the providers in @NgModule, you provide the mock using configureTestingModule. If you declare the providers in @Component, you provide the mock using overrideComponent. As discussed above: #10727 (comment), #10727 (comment)

More Issues: