使用Mock ActivatedRoute配置进行单元测试路由

时间:2019-05-24 09:51:59

标签: angular typescript unit-testing karma-jasmine

我正在为具有路由的组件配置测试规范,同时我还定义了具有相关性的规范,如下所示。而且ActivatedRoute具有这些属性,但是我在调​​试测试规范时看不到其对象/实例正在创建。我还提到了模拟ActivatedRoute的不同方法,但没有任何帮助。如果我做错了什么,请纠正我

class UserInfotypeDetailComponent implements OnInit, OnDestroy {
    constructor(
        private userInfotypeDetailService: UserInfotypeDetailService,
        private appLookupService: AppLookupService,
        private router: Router,
        private activatedRoute: ActivatedRoute
    ) {}

 performAction(event: { action: string; objectKey: string | null }) {
    let extras: any = { relativeTo: this.activatedRoute };
    if (event.objectKey) {
          extras.queryParams = { objectKey: event.objectKey };
    }

    switch (event.action) {
      case "new":
      case "edit":
      case "copy":
      case "view":
        this.router.navigate([event.action], extras);
        break;
      case "delete":
        this.deleteRecord(event.objectKey as string);
    }
  }

}

这是我的路线:

{
        path: "infotype/:id",
        component: UserInfotypeDetailComponent,
        outlet: "slidein",
        children: [
          {
            path: "new",
            component: UserRecordFormComponent,
            data: { actionId: "A", buttonDesc: "Save" }
          },
          {
            path: "edit",
            component: UserRecordFormComponent,
            data: { actionId: "E", buttonDesc: "Update" }
          },
          {
            path: "copy",
            component: UserRecordFormComponent,
            data: { actionId: "C", buttonDesc: "Save" }
          },
          {
            path: "view",
            component: UserRecordFormComponent,
            data: { actionId: "V", actionDesc: "View" }
          }
        ]
      }

我的测试规格如下:

beforeEach(async(() => {
        TestBed.configureTestingModule({
            imports: [
              RouterTestingModule.withRoutes([]),
                BrowserAnimationsModule,
                RouterModule
            ],
            declarations: [
                UserInfotypeDetailComponent
            ],
            providers: [
                { provide: ActivatedRoute, useValue: {
                                          outlet: "slidein",
                                          params: of({ 
                                              id: "0009"
                                          })
                                      }
                },
                { provide: AppLookupService, useClass: AppLookupServiceStub },
                { provide: UserInfotypeDetailService, useClass: UserInfotypeDetailServiceStub },
                { provide: Router, useClass: AppRouterStub }
            ],
            schemas: [NO_ERRORS_SCHEMA]
        }).compileComponents();
    }));

    class AppRouterStub {
        navigate() {}
    }

和测试用例:

it('make expect calls to router navigate', fakeAsync(() => {
      let router = TestBed.get(Router);
      let spy = spyOn(router, 'navigate');

      component.performAction(event);

      let extras: any = { relativeTo: ActivatedRoute };
      if (event.objectKey) {
        extras.queryParams = { objectKey: event.objectKey };
      }
      fixture.detectChanges();

      expect(spy).toHaveBeenCalledWith([event.action], extras);
    }))

它引发的错误是:

  

“间谍导航到已通过[['e​​dit'],Object({relativeTo:Function,queryParams:Object({objectKey:'36353539363A393C3535353E352525252525253E3E3E3E363E363738363735363E35363536353535'})})进行了调用,但实际的调用是[['edit'] ,Object({relativeTo:Object({快照:Object({}),父对象:{{params:Subject({_isScalar:false,观察者:[],已关闭:false,isStopped:false,hasError:false,thrownError: null})}),参数:Subject({_isScalar:false,观察者:[],关闭:false,isStopped:false,hasError:false,thrownError:null}),queryParams:Subject({_isScalar:false,观察者:[ ],关闭:false,isStopped:false,hasError:false,thrownError:null}),testParams:Object({id:'0009'})}),queryParams:Object({objectKey:'36353539363A393C3535353E352525252525253253E3E3E3E3E363738363735363E35363536353535'] 。”

1 个答案:

答案 0 :(得分:0)

失败了,因为

let extras: any = { relativeTo: ActivatedRoute };

您实际上正在使用angular的ActivatedRoute,但是您应该使用的是在useValue中定义的providers

在组件public中激活路由constructor,以便我们可以访问它

public activatedRoute: ActivatedRoute,
public router : Router

尝试:

it('make expect calls to router navigate', fakeAsync(() => {
      spyOn(component.router, 'navigate');

      component.performAction(event);
      // I hope you have defined "event" somewhere in code, because I can't see
      // it anywhere here !

      let extras: any = { relativeTo: component.activatedRoute};
      if (event.objectKey) {
        extras.queryParams = { objectKey: event.objectKey };
      }

      expect(component.router.navigate).toHaveBeenCalledWith([event.action], extras);
    }))