question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Injecting a service into a Component using TestBed.overrideComponent no longer works

See original GitHub issue

Bug Report or Feature Request (mark with an x)

- [x ] bug report -> please search issues before submitting
- [ ] feature request

Versions.

@angular/cli: 1.4.4 node: 6.10.0 os: win32 x64 @angular/animations: 4.4.4 @angular/cdk: 2.0.0-beta.11 @angular/common: 4.4.4 @angular/compiler: 4.4.4 @angular/core: 4.4.4 @angular/forms: 4.4.4 @angular/http: 4.4.4 @angular/material: 2.0.0-beta.11 @angular/platform-browser: 4.4.4 @angular/platform-browser-dynamic: 4.4.4 @angular/router: 4.4.4 @angular/cli: 1.4.4 @angular/compiler-cli: 4.4.4 @angular/language-service: 4.4.4 typescript: 2.3.4

Repro steps.

I am injecting a service into a component using the @Component annotation / providers property:

@Component({
    providers: HelloWorldService
})
export class HelloWorldComponent {
    constructor(private helloWorldService: HelloWorldService) {}
}

After updating to @angular/cli@1.4.4, using the TestBed’s overrideComponent function to provide the service throws an error:

Error: No provider for HelloWorldService!

TestBed.configureTestingModule({
    declarations: [
        HelloWorldComponent
    ]
}).overrideComponent(HelloWorldComponent, {
    set: {
        providers: [
            { provide: HelloWorldService, useFactory: helloWorldService => new HelloWorldService(null) }
        ]
    }
}).compileComponents().then(() => {
    // ...
});

Providing the service using the configureTestingModule function also throws an error:

TestBed.configureTestingModule({
    declarations: [
        HelloWorldComponent
    ],
    providers: [
        { provide: HelloWorldService, useFactory: helloWorldService => new HelloWorldService(null) }
    ]
}).compileComponents().then(() => {
    // ...
});

No provider for Http!

I can only get the component to compile if I provide the service in both the configureTestingModule function and the overrideComponent function.

The log given by the failure.

Desired functionality.

Mention any other details that might be useful.

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Comments:15 (8 by maintainers)

github_iconTop GitHub Comments

4reactions
delastevecommented, Oct 10, 2017

The TestBed only knows about it’s providers. The component has it’s own injector as well. If you were to use the component way of providing your service, use the following:

.then(() => {
  const componentFixture = TestBed.createComponent(HelloWorldComponent);
  const service = componentFixture.componentRef.injector.get(HelloWorldService);
});
4reactions
delastevecommented, Oct 10, 2017

Providers ideally should be provided at the NgModule level, not the individual component level. Again, ideally. Should you however provide it on the component, here’s the passing code to make it work:

  beforeEach(async(() => {
    TestBed
      .configureTestingModule({
        declarations: [HelloWorldComponent]
      })
      .overrideComponent(HelloWorldComponent, {
        set: {
          providers: [
            { provide: HelloWorldService, useValue: new HelloWorldService(null) }
          ]
        }
      })
      .compileComponents();
  }));

But if you use the NgModule way (edited for brevity):

app.module.ts

@NgModule({
...
  providers: [
    HelloWorldService
  ],
...
})
export class AppModule { }

hello-world.component.ts

@Component({
  selector: 'app-hello-world',
  templateUrl: './hello-world.component.html',
  styleUrls: ['./hello-world.component.css']
})
export class HelloWorldComponent implements OnInit {

hello-world.component.spec.ts

TestBed
  .configureTestingModule({
    providers: [
      { provide: HelloWorldService, useValue: new HelloWorldService(null) }
    ],
    declarations: [HelloWorldComponent]
  })
  .compileComponents();
Read more comments on GitHub >

github_iconTop Results From Across the Web

Testing Dependency Injection • Angular - codecraft.tv
When the component is created since it has its own injector it will resolve the AuthService itself and not forward the request to...
Read more >
Overriding service provided in component - Stack Overflow
I have done this, and it has worked for me. Do it exactly like this: // Create the TestBed module const testBedModule =...
Read more >
Overriding Components for Testing - Rangle.io
Overriding Components for Testing. TestBed provides several functions to allow us to override dependencies that are being used in a test module.
Read more >
Component testing scenarios - Angular
For a use case in which TestBed.inject() does not work, see the Override component providers section that explains when and why you must...
Read more >
How to Override Component Providers in Angular Unit Tests
The way we usually provide and mock services in our unit tests won't work as expected in these cases ... We actually need...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found