我有一个ResumeAppliationComponents,它调用ngOnInit上的一个方法,该方法加载数据并有条件地导航到我们应用程序中的页面.添加了一些测试后,我发现路由.navigate正在调用navigate 5次.为什么路由在我的测试中堆叠这些呼叫?

组件:

export class ResumePageComponent implements OnInit {

  public applicationId: string = "";

  constructor(private router: Router, private activatedRoute: ActivatedRoute, private applicationFacade: CustomerApplicationFacade,
    private routingFacade: RoutingFacade) {
  }

  ngOnInit(): void {
    this.loadAndNavigate();
  }

  public loadAndNavigate(): void {
    this.applicationFacade.commandLoadApplication(this.applicationId).subscribe((success) => {
      if (success) {
        const step = this.applicationFacade.getResumeApplicationStep()
        const page = step > -1 ? applicationDescriptor.pages.find(a => a.index == step) : null;
        if (page) {
          if (step < 2) {
            //if application not started, go to landing page. 
            this.router.navigate(['/apply/' + page.route]);
          } else {
            this.routingFacade.determinePageOnResume(page.id);
          }
        } else {
          this.router.navigate(['/portal/dashboard']);
        }
      } else {
        this.router.navigate(['/portal/dashboard']);
      }
    });
  }
}

测试 :

describe('ResumePageComponent', () => {
  let spectator: Spectator<ResumePageComponent>;
  let component: ResumePageComponent;
  const customerApplicationFacade = createSpyObject(CustomerApplicationFacade);
  let routingFacade: SpyObject<RoutingFacade> = createSpyObject(RoutingFacade);
  let mockRouter: SpyObject<Router> = createSpyObject(Router);

  const createComponent = createComponentFactory({
    component: ResumePageComponent,
    imports: [RouterTestingModule],
    declarations: [ResumePageComponent],
    providers: [
      { provide: CustomerApplicationFacade, useValue: customerApplicationFacade },
      { provide: Router, useValue: mockRouter },
      { provide: RoutingFacade, useValue: routingFacade },
      {
        provide: ActivatedRoute,
        useValue: {
          snapshot: {
            paramMap: {
              get: () => '1234',
            },
          },
        },
      }
    ]
  });

  beforeEach(async () => {
    customerApplicationFacade.commandLoadApplication.and.returnValue(of(true));
    spectator = createComponent();
    component = spectator.component;
    spyOn(component, 'loadAndNavigate').and.stub();
  });

  fit('should create', () => {
    expect(component).toBeTruthy();
  });

  fit('should navigate to dashboard if application is not loaded', () => {
    customerApplicationFacade.commandLoadApplication.and.returnValue(of(false));
    component.loadAndNavigate();
    expect(mockRouter.navigate).toHaveBeenCalledWith(['/portal/dashboard']);
  });

  fit('should navigate to dashboard if page index not found', () => {
    customerApplicationFacade.getResumeApplicationStep.and.returnValue(of(9999));
    component.loadAndNavigate();
    expect(mockRouter.navigate).toHaveBeenCalledWith(['/portal/dashboard']);
  });

  fit('should navigate to invite-begin if application step is 0', () => {
    customerApplicationFacade.getResumeApplicationStep.and.returnValue(of(0));
    component.loadAndNavigate();
    expect(mockRouter.navigate).toHaveBeenCalledWith(['/apply/invite-begin']);
    expect(routingFacade.determinePageOnResume).not.toHaveBeenCalled();
  });

  fit('should navigate to begin if application step is 1', () => {
    customerApplicationFacade.getResumeApplicationStep.and.returnValue(of(1));
    component.loadAndNavigate();
    expect(mockRouter.navigate).toHaveBeenCalledWith(['/apply/begin']);
    expect(routingFacade.determinePageOnResume).not.toHaveBeenCalled();
  });

  fit('should call determinePageOnResume when resume step is greater than 1', () => {
    customerApplicationFacade.getResumeApplicationStep.and.returnValue(of(2));
    component.loadAndNavigate();
    expect(routingFacade.determinePageOnResume).toHaveBeenCalled();
  });
});

我将ngOnInit的所有逻辑和导航移至它自己的方法中以减少呼叫,但路由不会在每次测试中重置.

推荐答案

您可以使用下面的代码重置间谍以判断最新值

 beforeEach(async () => {
     customerApplicationFacade.commandLoadApplication.and.returnValue(of(true));
     spectator = createComponent();
     component = spectator.component;
     
     routingFacade.determinePageOnResume.calls.reset(); // changed here!
     mockRouter.navigate.calls.reset(); // changed here!
    
     spyOn(component, 'loadAndNavigate').and.stub();
   });

Angular相关问答推荐

Angular 信号效果,try 重置表单并获取在计算或效果中不允许写入信号"

无法执行客户端功能Angular 17与ssr'

NG构建后多余的国旗

Change上的Angular 自定义控件无法正常工作

是否可以将Angular 路由配置为在点击带有本地人力资源S的锚点时更新Angular 路由?

AOS中的数据绑定--可能吗?

使用jsPDF生成带有图像的PDF时出现灰色条纹

自定义垫日历中选定的日期(Angular material )

在指令中获取宿主组件的templateRef

NX如何在前端和后端使用一个接口库

导入 AngularFirestoreModule 时出现问题:此类型参数可能需要 `extends firebase.firestore.DocumentData` 约束.

Angular 5 国际化

由router-outlet 创建时如何将css类应用于组件元素?

Angular2 + Jspm.io:使用类decorator 时需要反射元数据垫片

在Angular2的 Select 列表中设置最初 Select 的项目

Angular 2 单元测试 - @ViewChild 未定义

ngx-toastr,Toast 未在 Angular 7 中显示

angular2中的httpinterceptor类似功能是什么?

NG2-Charts 无法绑定到 datasets,因为它不是 canvas的已知属性

ng-template 上的 *ngFor 不输出任何内容