在Closed()之后模拟角材料对话框以进行单元测试

Bri*_*ley 3 unit-testing jasmine karma-jasmine angular-material angular

我正在使用以下功能打开Mat对话框:

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']);
    });
   }
 });
}
Run Code Online (Sandbox Code Playgroud)

我试图为此功能编写一个测试,该测试仅触发afterClosed(),以便可以检查是否调用了我的进行后端调用的服务方法。

component.spec.ts(在创建每个测试平台之前)

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();
}));
Run Code Online (Sandbox Code Playgroud)

component.spec.ts(测试)

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();
});
Run Code Online (Sandbox Code Playgroud)

该测试当前失败,并显示“已调用预期的间谍acceptLead”。我无法理解如何测试功能并执行某种模拟MatDialogRef,以便可以检查测试条件是否通过。

任何帮助/建议将不胜感激

小智 11

我在@Adithya Sreyaj 的第一篇文章中解决了这个问题,但添加了下一个更改:

spyOn(component.dialog, 'open')
    .and
    .returnValue({
        afterClosed: () => of(true)
    } as MatDialogRef<typeof component>);
Run Code Online (Sandbox Code Playgroud)

  • 这应该是排名第一的答案。 (2认同)
  • 我不确定这在 Jest 28 之后是否有效。我们现在必须使用 jest.spyOn 并且不能再使用 `.and.returnValue...` (2认同)

Adi*_*yaj 6

您可以通过以下方式测试“角度材质对话框”的afterClosed方法:

  1. import { of } from 'rxjs';
  2. 监视对话框并返回该afterClosed()方法的可观察值
spyOn(component.dialog, 'open')
     .and
     .returnValue({afterClosed: () => of(true)});
Run Code Online (Sandbox Code Playgroud)

基本上,afterClosed()dialogRef的期望值是Observable。因此,我们监视了组件的对话框打开方法,并afterClosed()使用的of运算符返回了该方法的Observable rxjs

然后,您可以使用自己的数据of(true)从中替换主组件中对话框中returnValue发送的afterClosed()

  • 它抛出错误。你能帮我吗?类型参数 '{ afterClosed: () =&gt; Observable&lt;boolean&gt;; }' 不可分配给类型为“MatDialogRef&lt;unknown,unknown&gt;”的参数。类型 '{ afterClosed: () =&gt; Observable&lt;boolean&gt;; }' 缺少类型“MatDialogRef&lt;unknown,unknown&gt;”中的以下属性:_overlayRef、_containerInstance、id、componentInstance 和 18 more.t (3认同)
  • @SunilSoni 那么`.open`通常应该返回一个`MatDialogRef`。在这种情况下,您只返回该对象的一小部分,因此 TypesScript 会对此进行抱怨。为了满足 TypeScript,您可以使用以下方式转换值:`.and.returnValue({ afterClosed: () =&gt; of(data) } as MatDialogRef&lt;unknown&gt;)`。但请注意,TypeScript 的抱怨是非常有效的。如果在测试中调用“MatDialogRef”的任何其他方法,则尝试调用“undefined”将会失败。 (3认同)