如何在 angular 7 中对 getCurrentNavigation().extras.state 进行单元测试

How to do unit testing for getCurrentNavigation().extras.state in angular 7

我正在尝试使用 jasmine 为 getCurrentNavigation() 编写单元测试。extras.state。

为了解决这个问题,我试过监视这个路由器方法。

我的组件文件,

@Component({
  selector: 'app-location-list',
  templateUrl: './location-list.component.html',
  styleUrls: ['./location-list.component.scss']
})
export class LocationListComponent implements OnInit{

  locationId;
  locationName;
  constructor(private activatedRoute: ActivatedRoute, private router: Router) {
    if (this.router.getCurrentNavigation().extras.state) {
      this.locationId = this.router.getCurrentNavigation().extras.state.locationId;
    }
    if (this.router.getCurrentNavigation().extras.state) {
      this.locationName = this.router.getCurrentNavigation().extras.state.locationName;
    }
  }
  ngOnInit() { }
}

我的规范文件,

describe('LocationListComponent ', () => {
  let component: LocationListComponent ;
  let fixture: ComponentFixture<LocationListComponent >;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      imports: [
        RouterTestingModule
      ],
      declarations: [
        LocationListComponent 
      ],
      providers: []
    })
      .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(LocationListComponent );
    component = fixture.componentInstance;
    spyOn(Router.prototype, 'getCurrentNavigation').and.returnValues({ 'extras': { 'state': { 'locationId': 100, 'locationName': "UK" } } });
    fixture.detectChanges();
  });

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

但是我收到以下错误,

TypeError: Cannot read property 'extras' of null

谁能帮我解决这个问题。我正在使用 Angular 7.2

您需要从 fixture 获取路由器实例

router = fixture.debugElement.injector.get(Router);

您可以使用 stubuseClass 轻松做到这一点,如果您可以在单独的文件和 export class RouterStub 中创建它,也可以在其他 spec 文件中重复使用, 试试:

spec 文件中创建一个 stub,其方法与 Router:

相同
class RouterStub{
 getCurrentNavigation(){
   return {
      extras: {
         state:{
           locationId: 'someId',
           locationName: 'someName'
         }
       }
     }
   }
}

并在 beforeEach() 块中:

describe('LocationListComponent ', () => {
  let component: LocationListComponent ;
  let fixture: ComponentFixture<LocationListComponent >;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      imports: [
        RouterTestingModule
      ],
      declarations: [
        LocationListComponent 
      ],
      providers: [ {provide: Router, useClass: RouterStub}]
    })
      .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(LocationListComponent );
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

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

如果我们尝试同时使用 RouterTestingModule{provide: Router, useClass: RouterStub} 它将抛出 cannot read property 'root' of undefined

的错误

所以我们可以直接为 Route 和它的 return 值创建 spy

describe('LocationListComponent', () => {
  let component: LocationListComponent ;
  let fixture: ComponentFixture<LocationListComponent>;
  let router: jasmine.SpyObj<Router>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      imports: [
        RouterTestingModule
      ],
      declarations: [
        LocationListComponent 
      ],
    })
      .compileComponents();
  }));

  beforeEach(() => {
    router = TestBed.get(Router);
    spyOn(router, 'getCurrentNavigation').and.returnValue({ extras: { state: { message: 'msg'} } } as any);
    fixture = TestBed.createComponent(LocationListComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

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

router.getCurrentNavigation() 的单元测试可以通过 3 个简单的步骤完成:

  1. 创建模拟路由器对象:

    const mockRouter = {
      getCurrentNavigation: jasmine.createSpy('getCurrentNavigation')
    };
    
  2. 将其注入 providers 数组:

    providers: [{ provide: Router, useValue: mockRouter }]
    
  3. Return beforeEach() 函数中所需的模拟值

    mockRouter.getCurrentNavigation.and.returnValue({
      extras: {
        state: {
          test: ''
        }
      }
    });