Angular 2.1 Cannot set base providers because it has already been called(…)
Asked Answered
W

2

9

I'm trying to test a basic angular 2 component that Includes a service. When I run my test I'm getting the following errors. The component, service and test are pretty small, they run fine in the browser as well. I'm not sure what I am missing from the test in order for it to work.

Any help is appreciated.

Uncaught Error: Cannot set base providers because it has already been called(…)

Uncaught Error: Error in ./TestComponent class TestComponent - inline template:0:0 caused by: No provider for Http!
Error: No provider for Http!
    at NoProviderError.BaseError [as constructor] (http://localhost:9876/base/karma-shim.js:4006:34)
    at NoProviderError.AbstractProviderError [as constructor] (http://localhost:9876/base/karma-shim.js:33221:16)
    at new NoProviderError (http://localhost:9876/base/karma-shim.js:33252:16)
    at ReflectiveInjector_._throwOrNull (http://localhost:9876/base/karma-shim.js:57969:19)
    at ReflectiveInjector_._getByKeyDefault (http://localhost:9876/base/karma-shim.js:57997:25)
    at ReflectiveInjector_._getByKey (http://localhost:9876/base/karma-shim.js:57960:25)
    at ReflectiveInjector_.get (http://localhost:9876/base/karma-shim.js:57769:21)
    at TestBed.get (http://localhost:9876/base/karma-shim.js:5778:67)
    at ElementInjector.get (http://localhost:9876/base/karma-shim.js:58133:48)
    at _View_TestComponent0.createInternal (TestComponent.ngfactory.js:21:68)
    at _View_TestComponent0.AppView.create (http://localhost:9876/base/karma-shim.js:58492:21)
    at _View_TestComponent0.DebugAppView.create (http://localhost:9876/base/karma-shim.js:58704:44)
    at _View_TestComponent_Host0.createInternal (TestComponent_Host.ngfactory.js:18:14)
    at _View_TestComponent_Host0.AppView.create (http://localhost:9876/base/karma-shim.js:58492:21)
    at _View_TestComponent_Host0.DebugAppView.create (http://localhost:9876/base/karma-shim.js:58704:44)
    at ComponentFactory.create (http://localhost:9876/base/karma-shim.js:33751:36)
    at initComponent (http://localhost:9876/base/karma-shim.js:5816:53)
    at ZoneDelegate.invoke (http://localhost:9876/base/karma-shim.js:48531:26)
    at ProxyZoneSpec.onInvoke (http://localhost:9876/base/karma-shim.js:48195:39)
    at ZoneDelegate.invoke (http://localhost:9876/base/karma-shim.js:48530:32)
    at Object.onInvoke (http://localhost:9876/base/karma-shim.js:22909:37)
    at ZoneDelegate.invoke (http://localhost:9876/base/karma-shim.js:48530:32)
    at Zone.run (http://localhost:9876/base/karma-shim.js:48413:43)
    at NgZone.run (http://localhost:9876/base/karma-shim.js:22799:62)
    at TestBed.createComponent (http://localhost:9876/base/karma-shim.js:5819:62)
    at Function.TestBed.createComponent (http://localhost:9876/base/karma-shim.js:5634:33)
    at Object.<anonymous> (http://localhost:9876/base/karma-shim.js:63273:41)
    at ZoneDelegate.invoke (http://localhost:9876/base/karma-shim.js:48531:26)
    at ProxyZoneSpec.onInvoke (http://localhost:9876/base/karma-shim.js:48195:39)
    at ZoneDelegate.invoke (http://localhost:9876/base/karma-shim.js:48530:32)
    at Zone.run (http://localhost:9876/base/karma-shim.js:48413:43)
    at Object.<anonymous> (http://localhost:9876/base/karma-shim.js:47910:34)
    at ZoneQueueRunner.jasmine.QueueRunner.ZoneQueueRunner.execute (http://localhost:9876/base/karma-shim.js:47940:42)
    at ZoneQueueRunner.jasmine.QueueRunner.ZoneQueueRunner.execute (http://localhost:9876/base/karma-shim.js:47940:42)
    at ZoneDelegate.invokeTask (http://localhost:9876/base/karma-shim.js:48564:35)
    at Zone.runTask (http://localhost:9876/base/karma-shim.js:48453:47)
    at drainMicroTaskQueue (http://localhost:9876/base/karma-shim.js:48700:35)

!-- the component

import { Component, OnInit } from '@angular/core';
import { TestService } from '../components/service/TestService';
@Component({
  selector: 'my-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.scss'],
  providers: [TestService]
})
export class HomeComponent implements OnInit {

  constructor(private testService: TestService) {
    // Do stuff
  }

  ngOnInit() {
    console.log('Hello Home', this.testService.getUsers());
  }

}

!-- the service

import { Injectable } from '@angular/core';
import { Http } from '@angular/http';

@Injectable()
export class TestService {
  constructor(public http: Http) {}

  getUsers() {
    return this.http.get('http://foo.bar');
  }
}

!-- the test

import { inject, TestBed } from '@angular/core/testing';

import {BaseRequestOptions, Response, ResponseOptions, Http} from '@angular/http';
import { MockBackend, MockConnection } from '@angular/http/testing';

import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing';
import {TestService} from './TestService';

TestBed.initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting());

describe('Http', () => {

  beforeEach(() => {
    TestBed.configureTestingModule({
      providers: [
        TestService,
        BaseRequestOptions,
        MockBackend,
        {
          provide: Http,
          useFactory: (backend: MockBackend, defaultOptions: BaseRequestOptions) => {
            return new Http(backend, defaultOptions);
          },
          deps: [MockBackend, BaseRequestOptions],
        },
      ],
    });
  });

  beforeEach(inject([MockBackend], (backend: MockBackend) => {
    const baseResponse = new Response(new ResponseOptions({ body: 'got response' }));
    backend.connections.subscribe((c: MockConnection) => c.mockRespond(baseResponse));
  }));

  it('should return response when subscribed to getUsers', inject([TestService], (testService: TestService) => {
    testService.getUsers().subscribe((res: Response) => {
      expect(res.text()).toBe('got response');
    });
  }));

});
Wastrel answered 30/10, 2016 at 0:51 Comment(7)
I don't see where you are trying to test the component. Are you sure you're showing us the correct test. I don't see the code above causing this error.Stig
Also, if you are going to call TestBed.initTestEvironment, then you should call TestBed.resetTestEnvironment before it. initTestEnvironment should only be called once if it is not reset. So in other test files if you are also calling it, then you should reset it for other tests before initializing itStig
hi @peeskillet, this is the correct test that I'm showing. I've not tried to remove the initTestEnvironment call. I'll give it a try and let you know if this has an effect.Wastrel
I didn't say to remove it. Normally this is called once in a test-shim file. If you are not using the test-shim, then you need to call it. But you need to reset it first, as you would be trying to call it in all the files. You don't know which file is going to be called first. so just add it to all the test files, but you need to reset it alsoStig
Ok, I've reset the TestBed.resetTestEnvironment(); then initialised it inside the beforeEach of my test. Now i'm receiving a no provider error from the test for http. >> zone.js:158Uncaught Error: Error in ./TestComponent class TestComponent - inline template:0:0 caused by: No provider for Http! Error: No provider for Http!Wastrel
I told you, you are not showing the correct test. The test you are showing does not have the TestComponent (which the error is about), nor does the test show anything about a HomeComponent, so I am not sure why you are showing that.Stig
Yes, you're absolutely right. Good to have a second pair of eyes.... Thanks for your help.Wastrel
C
16

I've fixed this problem doing the following:

move TestBed.initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting()); to the beforeAll function, so it look like this

describe('Http', () => {
    beforeAll( ()=> {
        TestBed.initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting());
    });
    beforeEach( () => {
       TestBed.configureTestingModule({
           providers : [...]
       }
    });
    it('your tests...', inject([Provider], (provider:Provider)=>{});
Crossindex answered 21/11, 2016 at 14:59 Comment(1)
This should be the accepted answer. Thanks a lot. It worked like a charm.Supposing
C
12

You might also get this message Cannot set base providers because it has already been called(…)

Because you do have a setupFilesAfterEnv in your jest config file.

And one of those setupFiles runs code which set base providers before you do.

Example:

jest.config.js

{
  setupFilesAfterEnv: ['<rootDir>/setup-jest.ts'],
}

setup-jest.ts

# remove this line
`import 'jest-preset-angular/setup-jest';`
Cronk answered 1/4, 2022 at 12:27 Comment(1)
@Tia I'm glad it helped you because it was a nightmare to debugCronk

© 2022 - 2024 — McMap. All rights reserved.