Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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');
    });
  }));

});
like image 328
Jimi Avatar asked Oct 30 '16 00:10

Jimi


2 Answers

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)=>{});
like image 171
Yevhenii Dovhaniuk Avatar answered Nov 17 '22 06:11

Yevhenii Dovhaniuk


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';`
like image 5
Flavien Volken Avatar answered Nov 17 '22 07:11

Flavien Volken