ng-mocks
Angular testing library for mocking components, directives, pipes, services and facilitating TestBed setup
Top Related Projects
Quick Overview
ng-mocks is a testing library for Angular applications that simplifies the process of creating mock components, directives, and services. It allows developers to easily isolate units of code for testing, reducing the complexity of test setup and improving test performance.
Pros
- Simplifies the creation of mock Angular components, directives, and services
- Reduces boilerplate code in unit tests
- Improves test performance by isolating units of code
- Supports both Jest and Jasmine testing frameworks
Cons
- Learning curve for developers new to mocking in Angular
- May require refactoring of existing tests to fully utilize its features
- Limited documentation for advanced use cases
- Potential overhead in simple test scenarios where full mocking isn't necessary
Code Examples
Creating a mock component:
import { MockComponent } from 'ng-mocks';
import { MyComponent } from './my.component';
const mockMyComponent = MockComponent(MyComponent);
Mocking a service:
import { MockProvider } from 'ng-mocks';
import { MyService } from './my.service';
TestBed.configureTestingModule({
providers: [
MockProvider(MyService)
]
});
Mocking inputs and outputs:
import { MockComponent } from 'ng-mocks';
import { Component } from '@angular/core';
@Component({
selector: 'app-child',
template: '<p>Child</p>'
})
class ChildComponent {
@Input() input: string;
@Output() output = new EventEmitter<string>();
}
const mockChildComponent = MockComponent(ChildComponent);
Getting Started
-
Install ng-mocks:
npm install ng-mocks --save-dev
-
Import and use in your test file:
import { MockComponent, MockProvider } from 'ng-mocks'; import { ComponentToTest } from './component-to-test.component'; import { DependencyService } from './dependency.service'; describe('ComponentToTest', () => { beforeEach(() => { TestBed.configureTestingModule({ declarations: [ComponentToTest, MockComponent(ChildComponent)], providers: [MockProvider(DependencyService)] }).compileComponents(); }); it('should create', () => { const component = TestBed.createComponent(ComponentToTest).componentInstance; expect(component).toBeTruthy(); }); });
Competitor Comparisons
Deliver web apps with confidence 🚀
Pros of Angular
- Comprehensive framework with built-in features for routing, forms, and HTTP
- Large ecosystem and community support
- Official framework maintained by Google
Cons of Angular
- Steeper learning curve due to its complexity
- Larger bundle size compared to lighter alternatives
- More opinionated, which may limit flexibility in some cases
Code Comparison
Angular:
@Component({
selector: 'app-root',
template: '<h1>{{ title }}</h1>'
})
export class AppComponent {
title = 'My Angular App';
}
ng-mocks:
const component = MockComponent(AppComponent);
const fixture = MockRender(component);
expect(fixture.point.componentInstance.title).toBe('My Angular App');
Key Differences
- Angular is a full-featured framework, while ng-mocks is a testing utility
- ng-mocks focuses on mocking Angular dependencies for unit tests
- Angular provides the core functionality, while ng-mocks enhances testing capabilities
Use Cases
- Angular: Building complete web applications
- ng-mocks: Simplifying unit tests for Angular components and services
Community and Support
- Angular: Large community, extensive documentation, and official support
- ng-mocks: Smaller but growing community, focused on testing scenarios
🦊 🚀 A Powerful Tool to Simplify Your Angular Tests
Pros of Spectator
- Provides a more comprehensive testing toolkit with built-in utilities for DOM querying and event simulation
- Offers a cleaner, more readable syntax for creating test beds and component fixtures
- Includes support for testing services, directives, and pipes out of the box
Cons of Spectator
- Steeper learning curve due to its extensive API and custom abstractions
- May introduce additional complexity for simpler test scenarios
- Less focused on mocking specific Angular features compared to ng-mocks
Code Comparison
ng-mocks:
const mock = MockComponent(UserProfileComponent);
TestBed.configureTestingModule({
declarations: [mock]
});
Spectator:
const spectator = createComponentFactory(UserProfileComponent);
const component = spectator.component;
Summary
Spectator offers a more comprehensive testing toolkit with built-in utilities and a cleaner syntax, making it suitable for complex testing scenarios. However, it may introduce additional complexity for simpler tests. ng-mocks focuses more on mocking Angular features and provides a simpler approach for basic component testing. The choice between the two depends on the specific testing needs and complexity of the project.
Fast, easy and reliable testing for anything that runs in a browser.
Pros of Cypress
- Comprehensive end-to-end testing framework with built-in assertions and commands
- Real-time browser testing with automatic waiting and retry mechanisms
- Extensive documentation and active community support
Cons of Cypress
- Limited to testing web applications, not suitable for native mobile apps
- Can be slower for large test suites compared to unit testing frameworks
- Learning curve for developers new to end-to-end testing concepts
Code Comparison
Cypress example:
describe('Login', () => {
it('should log in successfully', () => {
cy.visit('/login')
cy.get('#username').type('user@example.com')
cy.get('#password').type('password123')
cy.get('button[type="submit"]').click()
cy.url().should('include', '/dashboard')
})
})
ng-mocks example:
import { MockBuilder, MockRender } from 'ng-mocks';
import { LoginComponent } from './login.component';
describe('LoginComponent', () => {
beforeEach(() => MockBuilder(LoginComponent));
it('should render login form', () => {
const fixture = MockRender(LoginComponent);
expect(fixture.point.nativeElement.querySelector('form')).toBeTruthy();
});
});
While Cypress focuses on end-to-end testing in a browser environment, ng-mocks is specifically designed for unit testing Angular components and services. Cypress provides a more comprehensive testing solution for web applications, while ng-mocks excels in isolating and mocking Angular dependencies for focused unit tests.
Spectacular Test Runner for JavaScript
Pros of karma
- Widely adopted test runner for JavaScript projects, especially Angular
- Supports multiple browsers and continuous integration environments
- Extensive plugin ecosystem for added functionality
Cons of karma
- Steeper learning curve compared to ng-mocks
- Requires more configuration and setup
- Can be slower for large test suites due to browser-based execution
Code Comparison
karma configuration example:
module.exports = function(config) {
config.set({
frameworks: ['jasmine'],
files: ['src/**/*.js', 'test/**/*.js'],
browsers: ['Chrome'],
singleRun: true
});
};
ng-mocks usage example:
import { MockBuilder, MockRender } from 'ng-mocks';
import { TestComponent } from './test.component';
describe('TestComponent', () => {
beforeEach(() => MockBuilder(TestComponent));
it('should render', () => {
const fixture = MockRender(TestComponent);
expect(fixture.point.componentInstance).toBeTruthy();
});
});
Summary
karma is a versatile test runner suitable for various JavaScript projects, offering broad browser support and extensive customization. However, it may require more setup and can be slower for large test suites. ng-mocks, on the other hand, is specifically designed for Angular testing, providing a simpler setup process and faster execution for mock-based tests. The choice between the two depends on project requirements, team expertise, and testing strategy.
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME
Mock components, services and more out of annoying dependencies for simplification of Angular testing
ng-mocks
facilitates Angular testing and helps to:
- mock Components, Directives, Pipes, Modules, Services and Tokens
- reduce boilerplate in tests
- access declarations via simple interface
The current version of the library has been tested and can be used with:
Angular | ng-mocks | Jasmine | Jest | Ivy |
---|---|---|---|---|
18 | latest | yes | yes | yes |
17 | latest | yes | yes | yes |
16 | latest | yes | yes | yes |
15 | latest | yes | yes | yes |
14 | latest | yes | yes | yes |
13 | latest | yes | yes | yes |
12 | latest | yes | yes | yes |
11 | latest | yes | yes | yes |
10 | latest | yes | yes | yes |
9 | latest | yes | yes | yes |
8 | latest | yes | yes | |
7 | latest | yes | yes | |
6 | latest | yes | yes | |
5 | latest | yes | yes |
Important links
- Live example on CodeSandbox
- Live example on StackBlitz
- start a discussion on GitHub
- ask a question on Stackoverflow
- report an issue on GitHub
- chat on gitter
Very short introduction
Global configuration for mocks in src/test.ts
.
In case of jest, src/setup-jest.ts
/ src/test-setup.ts
should be used.
// All methods in mock declarations and providers
// will be automatically spied on their creation.
// https://ng-mocks.sudo.eu/extra/auto-spy
ngMocks.autoSpy('jasmine'); // or jest
// ngMocks.defaultMock helps to customize mocks
// globally. Therefore, we can avoid copy-pasting
// among tests.
// https://ng-mocks.sudo.eu/api/ngMocks/defaultMock
ngMocks.defaultMock(AuthService, () => ({
isLoggedIn$: EMPTY,
currentUser$: EMPTY,
}));
An example of a spec for a profile edit component.
// Let's imagine that there is a ProfileComponent
// and it has 3 text fields: email, firstName,
// lastName, and a user can edit them.
// In the following test suite, we would like to
// cover behavior of the component.
describe('profile:builder', () => {
// Helps to reset customizations after each test.
// Alternatively, you can enable
// automatic resetting in test.ts.
MockInstance.scope();
// Let's configure TestBed via MockBuilder.
// The code below says to mock everything in
// ProfileModule except ProfileComponent and
// ReactiveFormsModule.
beforeEach(() => {
// The result of MockBuilder should be returned.
// https://ng-mocks.sudo.eu/api/MockBuilder
return MockBuilder(
ProfileComponent,
ProfileModule,
).keep(ReactiveFormsModule);
// // or old fashion way
// return TestBed.configureTestingModule({
// imports: [
// MockModule(SharedModule), // mock
// ReactiveFormsModule, // real
// ],
// declarations: [
// ProfileComponent, // real
// MockPipe(CurrencyPipe), // mock
// MockDirective(HoverDirective), // mock
// ],
// providers: [
// MockProvider(AuthService), // mock
// ],
// }).compileComponents();
});
// A test to ensure that ProfileComponent
// can be created.
it('should be created', () => {
// MockRender is an advanced version of
// TestBed.createComponent.
// It respects all lifecycle hooks,
// onPush change detection, and creates a
// wrapper component with a template like
// <app-root ...allInputs></profile>
// and renders it.
// It also respects all lifecycle hooks.
// https://ng-mocks.sudo.eu/api/MockRender
const fixture = MockRender(ProfileComponent);
expect(
fixture.point.componentInstance,
).toEqual(assertion.any(ProfileComponent));
});
// A test to ensure that the component listens
// on ctrl+s hotkey.
it('saves on ctrl+s hot key', () => {
// A fake profile.
const profile = {
email: 'test2@email.com',
firstName: 'testFirst2',
lastName: 'testLast2',
};
// A spy to track save calls.
// MockInstance helps to configure mock
// providers, declarations and modules
// before their initialization and usage.
// https://ng-mocks.sudo.eu/api/MockInstance
const spySave = MockInstance(
StorageService,
'save',
jasmine.createSpy(), // or jest.fn()
);
// Renders <profile [profile]="params.profile">
// </profile>.
// https://ng-mocks.sudo.eu/api/MockRender
const { point } = MockRender(
ProfileComponent,
{ profile }, // bindings
);
// Let's change the value of the form control
// for email addresses with a random value.
// ngMocks.change finds a related control
// value accessor and updates it properly.
// https://ng-mocks.sudo.eu/api/ngMocks/change
ngMocks.change(
'[name=email]', // css selector
'test3@em.ail', // an email address
);
// Let's ensure that nothing has been called.
expect(spySave).not.toHaveBeenCalled();
// Let's assume that there is a host listener
// for a keyboard combination of ctrl+s,
// and we want to trigger it.
// ngMocks.trigger helps to emit events via
// simple interface.
// https://ng-mocks.sudo.eu/api/ngMocks/trigger
ngMocks.trigger(point, 'keyup.control.s');
// The spy should be called with the user
// and the random email address.
expect(spySave).toHaveBeenCalledWith({
email: 'test3@em.ail',
firstName: profile.firstName,
lastName: profile.lastName,
});
});
});
Profit.
Extra
If you like ng-mocks
, please support it:
Thank you!
P.S. Feel free to contact us if you need help.
Top Related Projects
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot