【问题标题】:How to test routing navigation with RouterTestingModule如何使用 RouterTestingModule 测试路由导航
【发布时间】:2021-10-04 04:38:30
【问题描述】:

我想测试将我发送到特定页面的方法。我检查了几个示例,所有示例都以与我相同的方式完成,但我收到一个错误:

预期的间谍导航已被调用: ['/主题'] 但它从未被调用过。 错误:预期的间谍导航已被调用: ['/主题'] 但它从未被调用过。

我的html代码是:

<button class="arrow-back-icon kf-tooltip-btn align-middle" id="backButton"
         tabindex="0" name="ic_arrow-back_24" (click)="goBack()">
</button>

我的组件中的方法是:

import {AfterViewChecked, ChangeDetectorRef, Component, OnInit} from '@angular/core';
import {TranslateService} from '@ngx-translate/core';
import {SharingDataService} from '../services/sharing-data.service';
import {ActivatedRoute, Router} from '@angular/router';
import {BreakpointObserver} from '@angular/cdk/layout';
@Component({
  selector: 'app-meeting',
  templateUrl: './meeting.component.html',
  styleUrls: ['./meeting.component.scss']
})
export class MeetingComponent implements OnInit, AfterViewChecked {
  constructor(private readonly translate: TranslateService,
              private readonly sharingDataService: SharingDataService,
              private readonly router: Router,
              private readonly activatedRoute: ActivatedRoute,
              private readonly breakpointObserver: BreakpointObserver,
              private readonly cd: ChangeDetectorRef) {
  }

goBack(): void {
  this.router.navigate(['/themen']).then();
}
}

测试是:

import {ComponentFixture, fakeAsync, inject, TestBed, waitForAsync} from '@angular/core/testing';
import {MeetingComponent} from './meeting.component';
import {Router, Routes} from '@angular/router';
import {CommonModule} from '@angular/common';
import {RouterTestingModule} from '@angular/router/testing';
import {TranslateLocalModule} from '../../../projects/shared/src/lib/translate';

describe('MeetingComponent', () => {
  let sut: meetingComponent;
  let fixture: ComponentFixture<MeetingComponent>;
  const routes: Routes = [
    {path: '', redirectTo: 'themen', pathMatch: 'full'},
    {path: 'meeting', component: meetingComponent},
    {path: '**', redirectTo: 'themen', pathMatch: 'full'}
  ];
  beforeEach(async () => {
    await TestBed.configureTestingModule({
      declarations: [ MeetingComponent ],
      imports: [
        CommonModule,
        RouterTestingModule.withRoutes(routes),
        TranslateLocalModule,
      providers: [
      ]
    }).compileComponents();
  });
  beforeEach(() => {fixture = TestBed.createComponent(MeetingComponent);
    sut = fixture.componentInstance;
    fixture.detectChanges();
  });
  it('should create', () => {
    expect(sut).toBeTruthy();
  });
  it('should go on previous step', waitForAsync(() => {
    const routerSpy = {
      navigate: jasmine.createSpy('navigate')
    };
    sut.onPrevStep();
    fixture.detectChanges();
    expect (routerSpy.navigate).toHaveBeenCalledWith('/themen');
  }));
});

谁能告诉我我做错了什么?

我也试过这个:

it('should navigates to previous step', fakeAsync(async () => {
  spyOn(sut, 'onPrevStep').and.returnValue(await Promise.resolve());
  const navigateSpy = spyOn(router, 'navigate');
  sut.onPrevStep();
  tick();
  expect(sut.onPrevStep).toHaveBeenCalled();
  expect(navigateSpy).toHaveBeenCalledWith(['/themen']);
}));

但错误是一样的。

谢谢!

【问题讨论】:

    标签: angular typescript unit-testing jasmine angular11


    【解决方案1】:

    是的,我认为您的routerSpy 与路由器无关。

    !!关注cmets

    试试这个:

    import {ComponentFixture, fakeAsync, inject, TestBed, waitForAsync} from '@angular/core/testing';
    import {MeetingComponent} from './meeting.component';
    import {Router, Routes} from '@angular/router';
    import {CommonModule} from '@angular/common';
    import {RouterTestingModule} from '@angular/router/testing';
    import {TranslateLocalModule} from '../../../projects/shared/src/lib/translate';
    
    describe('MeetingComponent', () => {
      let sut: meetingComponent;
      let fixture: ComponentFixture<MeetingComponent>;
      // !! add router variable for later use !!
      let router: Router;  
    
      const routes: Routes = [
        {path: '', redirectTo: 'themen', pathMatch: 'full'},
        {path: 'meeting', component: meetingComponent},
        {path: '**', redirectTo: 'themen', pathMatch: 'full'}
      ];
      beforeEach(async () => {
        await TestBed.configureTestingModule({
          declarations: [ MeetingComponent ],
          imports: [
            CommonModule,
            RouterTestingModule.withRoutes(routes),
            TranslateLocalModule,
          providers: [
          ]
        }).compileComponents();
      });
      beforeEach(() => {
        // !! get a handle on the router !!
        router = TestBed.inject(Router);
        fixture = TestBed.createComponent(MeetingComponent);
        sut = fixture.componentInstance;
        fixture.detectChanges();
      });
      it('should create', () => {
        expect(sut).toBeTruthy();
      });
      it('should go on previous step', waitForAsync(() => {
        // !! spy on the router !!
        spyOn(router, 'navigate');
        // !! I think this should be sut.goBack(); !!
        sut.onPrevStep();
        fixture.detectChanges();
        // !! change expectation !!
        expect(router.navigate).toHaveBeenCalledWith(['/themen']);
      }));
    });
    

    【讨论】:

    • 嗨! @AliF50,我照你说的做了,但我得到了新的错误:错误:未捕获(承诺中):TypeError:无法读取未定义的属性'then' TypeError:无法读取未定义的属性'then'
    【解决方案2】:

    在我的方法中,我有 this.router.navigate(['/themen']).then();这就是为什么当我应用@AliF50 解决方案时,它不起作用。如果我删除 .then() 测试解决方案可以正常工作。在这种情况下我可以做到,因为我在调用导航时不需要执行任何其他代码。

    但如果你这样做了,那么你必须提供一个承诺值。例如:

    import {ComponentFixture, fakeAsync, inject, TestBed, waitForAsync} from '@angular/core/testing';
    import {MeetingComponent} from './meeting.component';
    import {Router, Routes} from '@angular/router';
    import {CommonModule} from '@angular/common';
    import {RouterTestingModule} from '@angular/router/testing';
    import {TranslateLocalModule} from '../../../projects/shared/src/lib/translate';
    
    describe('MeetingComponent', () => {
      let sut: meetingComponent;
      let fixture: ComponentFixture<MeetingComponent>;
      let router: Router;  
    
      const routes: Routes = [
        {path: '', redirectTo: 'themen', pathMatch: 'full'},
        {path: 'meeting', component: meetingComponent},
        {path: '**', redirectTo: 'themen', pathMatch: 'full'}
      ];
      beforeEach(async () => {
        await TestBed.configureTestingModule({
          declarations: [ MeetingComponent ],
          imports: [
            CommonModule,
            RouterTestingModule.withRoutes(routes),
            TranslateLocalModule,
          providers: [
          ]
        }).compileComponents();
        !!The router spy must be declared here for me it did not work in the before each
        // !! get a handle on the router !!
        router = TestBed.inject(Router);
        // !! spy on the router and return a Promise Value!!
        spyOn(router, 'navigate').and.returnValue(Promise.resolve(true));     
      });
      beforeEach(() => {
        fixture = TestBed.createComponent(MeetingComponent);
        sut = fixture.componentInstance;
        fixture.detectChanges();
        router.initialNavigation();
      });
      it('should create', () => {
        expect(sut).toBeTruthy();
      });
      it('should go on previous step', waitForAsync(() => {
        sut.onPrevStep();
        expect(router.navigate).toHaveBeenCalledWith(['/themen']);
      }));
    });
    

    【讨论】:

      猜你喜欢
      • 2019-05-18
      • 2020-08-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-24
      • 1970-01-01
      • 2016-04-29
      • 1970-01-01
      相关资源
      最近更新 更多