问题
In one of our component, we use Renderer2
to add and remove some css classes/styles to the body element. To achieve that, we simply do something like:
this.renderer.setStyle(document.body, 'padding-left', '10px');
this.renderer.addClass(document.body, 'modal-container--opened');
As soon as we run the tests, we encounter errors:
Cannot read property 'add' of undefined
Cannot set property 'padding-left' of undefined
So it seems angular testBed doesn't create any body
element.
In our test configuration, how to create a mocked body element? So we can run our tests against that element and see if style/class was properly applied by renderer.
It also seems mocking the Renderer2 is not possible.
We tried to create a spy:
let renderer: jasmine.SpyObj<Renderer2>;
renderer = jasmine.createSpyObj('renderer', ['addClass', 'removeClass', 'setStyle']);
then in TestBed.configureTestingModule
(also tested in overrideProviders
without more success):
{ provide: Renderer2, useValue: renderer }
But Angular ignores completely this override.
How to be able to test our component behavior, acting on document.body
?
回答1:
Instead of mocking the renderer try to hijack it. This should be working with Angular 6+.
In your component.spec.ts:
let renderer2: Renderer2;
...
beforeEach(async( () => {
TestBed.configureTestingModule({
...
providers: [Renderer2]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(YourComponent);
// grab the renderer
renderer2 = fixture.componentRef.injector.get<Renderer2>(Renderer2 as Type<Renderer2>);
// and spy on it
spyOn(renderer2, 'addClass').and.callThrough();
// or replace
// spyOn(renderer2, 'addClass').and.callFake(..);
// etc
});
it('should call renderer', () => {
expect(renderer2.addClass).toHaveBeenCalledWith(jasmine.any(Object), 'css-class');
});
回答2:
Other approach would be, mocking service:
let renderer: MockRenderer;
class MockRenderer {
addClass(document: string, cssClass: string): boolean {
return true;
}
}
beforeEach(async( () => {
TestBed.configureTestingModule({
...
providers: [{
provide: Renderer2,
useClass: MockRenderer
}]
}).compileComponents().then(() => {
fixture = TestBed.createComponent(YourComponent);
renderer = fixture.debugElement.injector.get(Renderer2);
});
}));
...
it('should call render', () => {
spyOn(renderer, 'addClass');
...
expect(renderer.addClass).toHaveBeenCalledWith(jasmine.any(Object), 'css-class');
});
来源:https://stackoverflow.com/questions/48826434/make-the-component-test-to-have-a-body-or-mock-renderer2