How to mock a host directive
It can happen that a component hast a host directive which should be mocked in a test.
There are several ways how ng-mocks
can mock host directives:
MockBuilder
and itsshallow
flagMockBuilder
constructorTestBed
shallow
flag
It's the easiest and recommended way which covers all host directives automatically, so there is no need to specify all of them.
To mock all host directives, simply provide shallow
flag in MockBuilder.mock
:
beforeEach(() =>
MockBuilder().mock(TargetComponent, { shallow: true }),
);
Now, all host directives and their dependencies will be mocks.
MockBuilder
MockBuilder
is useful, when only one or some host directives should be mocked.
To do so, the host directives should be specified as the second parameter of MockBuilder
:
beforeEach(() => MockBuilder(TargetComponent, HostDirective));
That's it, now TargetComponent
will have a mock of HostDirective
.
TestBed
If you use TestBed
, you should mock the desired host directive with MockDirective
and import / declare its component.
For example, if the name of the component is TargetComponent
and its host directive is called HostDirective
,
then TestBed
can be defined like that:
beforeEach(() =>
TestBed.configureTestingModule({
imports: [MockDirective(HostDirective)], // mocking the host directive
declarations: [TargetComponent], // declaring the component under test
}).compileComponents(),
);
Profit! Under the hood TargetComponent
will be redefined to use a mock of HostDirective
.
Live example
import {
Component,
Directive,
EventEmitter,
Input,
Output,
} from '@angular/core';
import { TestBed } from '@angular/core/testing';
import {
MockBuilder,
MockDirective,
MockRender,
ngMocks,
} from 'ng-mocks';
@Directive({
selector: 'host',
standalone: true,
})
class HostDirective {
@Input() input?: string;
@Output() output = new EventEmitter<void>();
public hostMockHostDirective() {}
}
@Component({
selector: 'target',
hostDirectives: [
{
directive: HostDirective,
inputs: ['input'],
outputs: ['output'],
},
],
template: 'target',
})
class TargetComponent {
public targetMockHostDirective() {}
}
describe('MockHostDirective', () => {
describe('TestBed', () => {
beforeEach(() =>
TestBed.configureTestingModule({
imports: [MockDirective(HostDirective)],
declarations: [TargetComponent],
}),
);
it('mocks host directives', () => {
const fixture = TestBed.createComponent(TargetComponent);
const directive = ngMocks.findInstance(fixture, HostDirective);
expect(directive).toBeDefined();
});
});
describe('MockBuilder', () => {
beforeEach(() => MockBuilder(TargetComponent, HostDirective));
it('mocks host directives', () => {
MockRender(TargetComponent, { input: 'test' });
const directive = ngMocks.findInstance(HostDirective);
expect(directive.input).toEqual('test');
});
});
describe('MockBuilder:shallow', () => {
beforeEach(() =>
MockBuilder().mock(TargetComponent, { shallow: true }),
);
it('mocks host directives', () => {
MockRender(TargetComponent, { input: 'test' });
const directive = ngMocks.findInstance(HostDirective);
expect(directive.input).toEqual('test');
});
});
});