我有一个 ResumeApplicationComponent,它调用 ngOnInit 上的一个方法来加载数据并有条件地导航到我们应用程序中的页面。添加一些测试后,我收到了 router.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();
});