Carlos Cifuentes
AngularJS → Angular reference

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 · Angular
describe('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