ngMock unit tests (module, inject, $controller) in modern Angular
module() and inject() from ngMock become TestBed. A test imports the standalone component, replaces its dependencies with fakes and checks the rendered DOM.
Before · AngularJS
describe('CartCtrl', function () {
var ctrl, CartService;
beforeEach(module('app'));
beforeEach(inject(function ($controller, _CartService_) {
CartService = _CartService_;
spyOn(CartService, 'total').and.returnValue(30);
ctrl = $controller('CartCtrl');
}));
it('shows the total', function () {
expect(ctrl.total).toBe(30);
});
});After · Angulardescribe('CartComponent', () => {
it('shows the total', () => {
TestBed.configureTestingModule({
imports: [CartComponent],
providers: [{ provide: CartService, useValue: { total: () => 30 } }],
});
const fixture = TestBed.createComponent(CartComponent);
fixture.detectChanges();
const total = fixture.nativeElement.querySelector('.total');
expect(total.textContent).toContain('30');
});
});What changes
- module('app') loaded the whole application; TestBed loads only the component under test and the providers you list.
- $controller tested the controller without its template; a fixture renders the template too, so the test covers what the user sees.
- The underscore injection (_CartService_) becomes TestBed.inject(CartService).
Migration tip. Do not port old specs line by line. Keep their names as a checklist of behavior and rewrite each case against the rendered component; component harnesses from @angular/cdk/testing help keep DOM queries out of the test body.
Related
Planning a migration or a micro-frontend platform?
In a 20-minute call you describe your situation and I tell you how I'd approach it. If it isn't worth doing yet, I'll say so.
Message me on LinkedIn