Security News
38% of CISOs Fear They’re Not Moving Fast Enough on AI
CISOs are racing to adopt AI for cybersecurity, but hurdles in budgets and governance may leave some falling behind in the fight against cyber threats.
ng-mocks is a powerful library for Angular that simplifies the process of creating mock components, directives, pipes, and services for unit testing. It helps developers to isolate the unit of work and test it without dependencies on other parts of the application.
Mock Components
This feature allows you to create mock versions of Angular components. This is useful for isolating the component under test from its child components.
import { MockComponent } from 'ng-mocks';
import { MyComponent } from './my-component';
TestBed.configureTestingModule({
declarations: [MockComponent(MyComponent)]
});
Mock Directives
This feature allows you to create mock versions of Angular directives. This is useful for isolating the component under test from its directives.
import { MockDirective } from 'ng-mocks';
import { MyDirective } from './my-directive';
TestBed.configureTestingModule({
declarations: [MockDirective(MyDirective)]
});
Mock Pipes
This feature allows you to create mock versions of Angular pipes. This is useful for isolating the component under test from its pipes.
import { MockPipe } from 'ng-mocks';
import { MyPipe } from './my-pipe';
TestBed.configureTestingModule({
declarations: [MockPipe(MyPipe)]
});
Mock Services
This feature allows you to create mock versions of Angular services. This is useful for isolating the component under test from its services.
import { MockProvider } from 'ng-mocks';
import { MyService } from './my-service';
TestBed.configureTestingModule({
providers: [MockProvider(MyService)]
});
Jest is a delightful JavaScript testing framework with a focus on simplicity. It provides a powerful mocking library that can be used to mock functions, modules, and timers. While Jest is not specific to Angular, it can be used in conjunction with Angular to achieve similar mocking capabilities.
Sinon is a standalone test spies, stubs, and mocks library for JavaScript. It works with any unit testing framework and provides powerful mocking capabilities. Like Jest, Sinon is not specific to Angular but can be used to mock dependencies in Angular applications.
ts-mockito is a mocking library for TypeScript inspired by the Java library Mockito. It provides a simple API for creating mock objects and verifying interactions. ts-mockito is not specific to Angular but can be used to mock dependencies in Angular applications.
Helper function for creating angular mocks for test.
Sure, you could flip a flag on schema errors to make your component dependencies not matter. Or you could use this to mock them out and have the ability to assert on their inputs or emit on an output to assert on a side effect.
ng-content
tags to allow transclusion@ContentChild
is present, then all of them will be wrapped as [data-key="_id_"]
and ng-content
with [data-key="ng-content"]
onChanged
on the mocked component bound to a FormControlonTouched
on the mocked component bound to a FormControlimport { async, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { MockComponent } from 'ng-mocks';
import { DependencyComponent } from './dependency.component';
import { TestedComponent } from './tested.component';
describe('TestedComponent', () => {
let fixture: ComponentFixture<TestedComponent>;
beforeEach(async() => {
TestBed.configureTestingModule({
declarations: [
TestedComponent,
MockComponent(DependencyComponent)
]
})
.compileComponents();
.then(() => {
fixture = TestBed.createComponent(TestedComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
}));
it('should send the correct value to the dependency component input', () => {
// let's pretend Dependency Component (unmocked) has 'someInput' as an input
// the input value will be passed into the mocked component so you can assert on it
const mockedComponent = fixture.debugElement
.query(By.css('dependency-component-selector'))
.componentInstance as DependencyComponent; // casting to retain type safety
expect(mockedComponent.someInput).toEqual('foo'); // if you casted mockedComponent as the original component type then this is type safe
});
it('should do something when the dependency component emits on its output', () => {
const mockedComponent = fixture.debugElement
.query(By.directive(MockComponent(DependencyComponent)))
.componentInstance as DependencyComponent; // casting to retain type safety
// again, let's pretend DependencyComponent has an output called 'someOutput'
// emit on the output that MockComponent setup when generating the mock of Dependency Component
mockedComponent.someOutput.emit(new Foo()); // if you casted mockedComponent as the original component type then this is type safe
fixture.detectChanges();
// assert on some side effect
});
// <mocked-dependency-component><p>inside content</p></mocked-dependency-component>
it('should render something inside of the dependency component', () => {
// because component does not have any @ContentChild we can access html directly.
const mockedNgContent = fixture.debugElement
.query(By.directive(MockComponent(DependencyComponent)))
.innerHTML;
expect(mockedNgContent).toContain('<p>inside content</p>');
fixture.detectChanges();
// assert on some side effect
});
// <mocked-dependency-component>
// <ng-template #something><p>inside something</p></ng-template>
// <p>inside content</p>
// </mocked-dependency-component>
it('should render something inside of the dependency component', () => {
// because component does have @ContentChild we need to use wrappers.
const mockedNgContent = fixture.debugElement
.query(By.directive(MockComponent(DependencyComponent)))
.query(By.css('[data-key="ng-content"]'))
.innerHTML;
expect(mockedNgContent).toContain('<p>inside content</p>');
const mockedNgTemplate = fixture.debugElement
.query(By.directive(MockComponent(DependencyComponent)))
.query(By.css('[data-key="something"]'))
.innerHTML;
expect(mockedNgTemplate).toContain('<p>inside something</p>');
fixture.detectChanges();
// assert on some side effect
});
});
import { async, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { MockComponent } from 'ng-mocks';
import { DependencyDirective } from './dependency.directive';
import { TestedComponent } from './tested.component';
describe('TestedComponent', () => {
let fixture: ComponentFixture<TestedComponent>;
beforeEach(async() => {
TestBed.configureTestingModule({
declarations: [
TestedComponent,
MockDirective(DependencyDirective)
]
})
.compileComponents();
.then(() => {
fixture = TestBed.createComponent(TestedComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
}));
it('should send the correct value to the dependency component input', () => {
// let's pretend Dependency Directive (unmocked) has 'someInput' as an input
// the input value will be passed into the mocked directive so you can assert on it
const debugElement = fixture.debugElement.query(By.directive(MockDirective(DependencyDirective)));
const mockedDirectiveInstance = debugElement.injector
.get(MockDirective(DependencyDirective)) as DependencyDirective; // casting to retain type safety
expect(mockedDirectiveInstance.someInput).toEqual('foo');
});
it('should do something when the dependency directive emits on its output', () => {
const debugElement = fixture.debugElement.query(By.directive(MockDirective(DependencyDirective)));
const mockedDirectiveInstance = debugElement.injector
.get(MockDirective(DependencyDirective)) as DependencyDirective; // casting to retain type safety
// again, let's pretend DependencyDirective has an output called 'someOutput'
// emit on the output that MockDirective setup when generating the mock of Dependency Directive
mockedDirectiveInstance.someOutput.emit(new Foo()); // if you casted mockedDirective as the original component type then this is type safe
fixture.detectChanges();
// assert on some side effect
});
});
Personally, I found the best thing to do for assertions is to override the transform to write the args so that I can assert on the arguments.
import { async, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { MockComponent } from 'ng-mocks';
import { DependencyPipe } from './dependency.pipe';
import { TestedComponent } from './tested.component';
describe('TestedComponent', () => {
let fixture: ComponentFixture<TestedComponent>;
beforeEach(async() => {
TestBed.configureTestingModule({
declarations: [
TestedComponent,
MockPipe(DependencyPipe, (...args) => JSON.stringify(args)), // alternatively you can use MockPipes to mock multiple but you lose the ability to override
]
})
.compileComponents();
.then(() => {
fixture = TestBed.createComponent(TestedComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
}));
describe('with transform override', () => {
it('should return the result of the provided transform function', () => {
expect(fixture.debugElement.query(By.css('#elementUsingPipe')).nativeElement.innerHTML).toEqual('foo');
});
});
});
MockedComponent
type to stay typesafe: MockedComponent<YourReactiveFormComponent>
import { async, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { MockComponent, MockedComponent } from 'ng-mocks';
import { ReactiveFormComponent } from './dependency.component';
import { TestedComponent } from './tested.component';
describe('TestedComponent', () => {
let fixture: ComponentFixture<TestedComponent>;
beforeEach(async() => {
TestBed.configureTestingModule({
declarations: [
TestedComponent,
MockComponent(DependencyComponent)
]
})
.compileComponents();
.then(() => {
fixture = TestBed.createComponent(TestedComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
}));
it('should send the correct value to the dependency component input', () => {
const mockedReactiveFormComponent = fixture.debugElement
.query(By.css('dependency-component-selector'))
.componentInstance as MockedComponent<ReactiveFormComponent>; // casting to retain type safety
mockedReactiveFormComponent.__simulateChange('foo');
expect(component.formControl.value).toBe('foo')
});
});
It figures out if it is a component, directive, or pipe and mocks it for you
For providers I typically will use TestBed.get(SomeProvider) and extend it using a library like ts-mocks.
describe('MockModule', () => {
let fixture: ComponentFixture<ComponentSubject>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [
ComponentSubject
],
imports: [
MockModule(DependencyModule)
],
})
.compileComponents()
.then(() => {
fixture = TestBed.createComponent(ComponentSubject);
fixture.detectChanges();
});
}));
});
Report it as an issue or submit a PR. I'm open to contributions.
FAQs
An Angular testing library for creating mock services, components, directives, pipes and modules in unit tests. It provides shallow rendering, precise stubs to fake child dependencies. ng-mocks works with Angular 5 6 7 8 9 10 11 12 13 14 15 16 17 18, jasm
We found that ng-mocks demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
CISOs are racing to adopt AI for cybersecurity, but hurdles in budgets and governance may leave some falling behind in the fight against cyber threats.
Research
Security News
Socket researchers uncovered a backdoored typosquat of BoltDB in the Go ecosystem, exploiting Go Module Proxy caching to persist undetected for years.
Security News
Company News
Socket is joining TC54 to help develop standards for software supply chain security, contributing to the evolution of SBOMs, CycloneDX, and Package URL specifications.