Can't provide mock for Renderer during component tests
See original GitHub issueI’m submitting a … (check one with “x”)
[x] bug report => search github for a similar issue or PR before submitting
[ ] feature request
[ ] support request => Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question
Current behavior
I Have a component which uses the Renderer via dependency injection. In my component test I provide Renderer mock instead of the real one. When running the test, the real Renderer is being injected instead of my mock (DebugDomRenderer).
Expected behavior
Renderer mock should be injected during the component test instead of the real one.
Minimal reproduction of the problem with instructions
- Use the Renderer in component via DI:
import { Component, ElementRef, Renderer } from '@angular/core';
@Component({
selector: 'app-main',
templateUrl: './main.component.html',
styleUrls: ['./main.component.less']
}) export class MainComponent {
@Input() globalInputRef: ElementRef;
constructor(private renderer:Renderer) {
}
setColor() {
this.renderer.setElementStyle(this.globalInputRef.nativeElement, 'backgroundColor', 'yellow');
}
}
- Create renderer mock with spies, inject it on tests:
describe('Main component tests', () => {
let fixture: ComponentFixture<MainComponent>,
component: MainComponent;
const rendererMock = jasmine.createSpyObj('rendererMock', ['setElementStyle']);
beforeEach(done => {
TestBed.configureTestingModule({
declarations: [MainComponent],
schemas: [NO_ERRORS_SCHEMA]
}).overrideComponent(MainComponent, {
set: {
providers: [
{provide: Renderer, useValue: rendererMock}
]
}
});
TestBed.compileComponents().then(() => {
fixture = TestBed.createComponent(MainComponent);
component = fixture.componentInstance;
done();
});
});
it('should inject renderer mock', () => {
component.globalInputRef = {nativeElement: 'nativeElement'};
component.setColor();
expect(rendererMock.setElementStyle).toHaveBeenCalled();
});
});
Karma fails because it tries to call real functions from the real Renderer (DebugDomRenderer).
Workaround: Inject the Injector, and use it to inject the Renderer: in MainComponent class:
constructor(injector:Injector) {
this.renderer = injector.get(Renderer);
}
What is the motivation / use case for changing the behavior?
Isolating my component from outer services/modules during tests.
Please tell us about your environment:
OS: macOS Sierra 10.12.1 IDE: WebStorm npm: v4.1.1
- Angular version: 2.1.0
- Browser: all
-
Language: TypeScript 2.0.7
-
Node (for AoT issues):
node --version= v6.9.2
Issue Analytics
- State:
- Created 7 years ago
- Comments:7 (1 by maintainers)
Top Related StackOverflow Question
@DzmitryShylovich Thanks for the quick respond! I ended up creating my own custom renderer with spies for tests.
The above did not work for me on Angular v6.
Instead of mocking the renderer try to hijack it…
In your component.spec.ts