Bigeyes
Bigeyes

Reputation: 1686

How yo mock Overlay, OverlayRef and Injector in angular testing?

I have a popup service.

@Injectable()
export class PopupService {
   private _modal: ModalRef | null = null;
   constructor(private overlay: Overlay,
               private readonly overlayRef: OverlayRef,
               private parentInjector: Injector) {}
   open(data: PopupConfig) {
      const overlayRef = this.overlay.create(this._getModalConfig());
      const modalRef = newModalRef(overlayRef);
      const injector = this._getInjector(data, modelRef, this.parentInjector);
      const portal = new ComponentPortal(PopupComponent, null, injector);
      overlayRef.attach(portal);
      return modalRef;
   }
}

My question is that I want to do unit test for this service, but the service has a few dependencies. I don't know how to mock them in the providers. Now the error is No provider for PopupService.

I guess that the code might be like

providers: [
   Overlay,{provider: Overlay, useValue: fakeOverlay},
   OverlayRef, {provide: OverlayRef, useValue: fakeOverlayRef},
   Injector, {provider: Injector, useValue: fakeInjector}
]

The thing is how to create those fake values. I assume

const fakeOverlay = jasime.createSpyObj('Overlay', []);
const fakeOverlayRef = jasime.createSpyObj('OverlayRef', []);
const fakeInjector = jasime.createSpyObj('Injector', []);

Is it right?

Upvotes: 1

Views: 734

Answers (1)

satanTime
satanTime

Reputation: 13574

You are right. It looks like, you forgot to add PopupService to the providers, also use provide, not provider:

providers: [
  PopupService, // <-- add it
  // provide, not provider
  {provide: Overlay, useValue: fakeOverlay},
  // provide, not provider
  {provide: OverlayRef, useValue: fakeOverlayRef},

  // might now always work, because Angular depends on the real injector.
  // better to mock what the injector gets in your service.
  // provide, not provider
  {provide: Injector, useValue: fakeInjector},
],

Instead of mocking everything manually, you can use ng-mocks and let it create mocks automatically.

beforeEach(() => {
  return MockBuilder(PopupService, ItsModule);
});

ng-mocks will mock everything what is declared and provided in ItsModule, whereas PopupService will stay as it is. So all its dependencies will be mocks.

Upvotes: 1

Related Questions