Mocking Angular Material Dialog afterClosed() for unit test

喜你入骨 提交于 2019-12-10 19:09:27

问题


I am opening my mat-dialog with the following function:

accept() {
 let dialogRef = this.dialog.open(AcceptDialogComponent, {
  data: {
    hasAccepted: false
      }
    })
 dialogRef.afterClosed().subscribe(result => {
  console.log(result);
  if (result.hasAccepted === true) {
    this.leadService.acceptLead(this.holdingAccountId, this.lead.id)
    .pipe(
      takeUntil(this.onDestroy$)
    )
    .subscribe (acceptLeadRes => {
      console.log(acceptLeadRes);
      this.leadService.updateLeadAction('accept');
    },
    (err: HttpErrorResponse) => {
      console.log(err);
      this.router.navigate(['/error']);
    });
   }
 });
}

I am attempting to write a test for this function that simply fires the afterClosed() so that I can check if my service method that makes a backend call is called.

component.spec.ts (beforeEach Testbed creation)

beforeEach(async(() => {
TestBed.configureTestingModule({
  declarations: [ LeadCardComponent, AcceptDialogComponent ],
  imports: [ 
    requiredTestModules,
    JwtModule.forRoot({
      config: {
        tokenGetter: () => {
          return '';
        }
      }
    })
  ],
  providers: [ 
    ApplicationInsightsService,
    JwtHelperService,
    // { provide: LeadsService, useValue: leadServiceSpy }
  ],
}),

TestBed.overrideModule(BrowserDynamicTestingModule, {
  set: {
     entryComponents: [ AcceptDialogComponent ]
   }
 });
TestBed.compileComponents();
}));

component.spec.ts (test)

it('Return from AcceptLeadDialog with hasAccepted equals true should call acceptLead endpoint', () => {
  let matDiaglogref = dialog.open(AcceptDialogComponent, {
     data: {
        hasAccepted: false
     }
  });
  spyOn(matDiaglogref, 'afterClosed').and.callThrough().and.returnValue({ hasAccepted: true });
  spyOn(leadService, 'acceptLead').and.callThrough();
  component.acceptLead();
  fixture.detectChanges();
  matDiaglogref.close();
  fixture.detectChanges();

  expect(leadService.acceptLead).toHaveBeenCalled();
});

The test currently fails with a "Expected spy acceptLead to have been called." I am failing on understanding how to test the function and execute some sort of mock MatDialogRef so that I can check if the conditions of my test pass.

Any help/suggestions would be much appreciated


回答1:


You can test Angular Material Dialog's afterClosed method this way:

  1. import { of } from 'rxjs';
  2. spy on the dialog and return an observable for the afterClosed() method
spyOn(component.dialog, 'open')
     .and
     .returnValue({afterClosed: () => of(true)});

Basically, the afterClosed() of the dialogRef is expecting an Observable. So we spy on the component's dialog open method and return an Observable for the afterClosed() method by using the of operator from rxjs.

You can then replace the of(true) from the returnValue with your own data what you are sending in the afterClosed() of the dialog in the main component.




回答2:


I think you are missing the whole point of unit testing the component. From my understanding:

  1. You have a function accept() which creates subscription to the closing event of this.dialog
  2. You should write unit test to verify the logic that the subscription is getting created and the service is called.
  3. Make dialogRef global to component rather than keeping it private to accept(). This would help you test your code better. private variables can't be access during unit testing.

So:

component.ts

accept() {
 this.dialogRef = this.dialog.open(AcceptDialogComponent, {
  data: {
    hasAccepted: false
      }
    })
 this.dialogRef.afterClosed().subscribe(result => {
  console.log(result);
  if (result.hasAccepted === true) {
    this.leadService.acceptLead(this.holdingAccountId, this.lead.id)
    .pipe(
      takeUntil(this.onDestroy$)
    )
    .subscribe (acceptLeadRes => {
      console.log(acceptLeadRes);
      this.leadService.updateLeadAction('accept');
    },
    (err: HttpErrorResponse) => {
      console.log(err);
      this.router.navigate(['/error']);
    });
   }
 });
}

spec.ts

it('should create subscription to Modal closing event and call "acceptLead()" of "leadService" ', () => {
    spyOn(component.dialogRef, 'afterClosed').and.returnValue(
        of({
            hasAccepted: false
        })
    );
    spyOn(component.leadService, 'acceptLead').and.callThrough();
    component.accept();
    expect(component.dialogRef).toBeDefined();
    expect(component.dialogRef.afterClosed).toHaveBeenCalled();
    expect(component.leadService.acceptLead).toHaveBeenCalled();
});




来源:https://stackoverflow.com/questions/56030253/mocking-angular-material-dialog-afterclosed-for-unit-test

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!