karma angular测试路由导航

huangapple go评论52阅读模式
英文:

karma angular test router navigate

问题

我正在开发一个Angular练习应用程序,并使用Karma和Jasmine进行测试。我试图测试路由器的导航功能。问题是这个调用在一个then()内部。我认为由于是异步操作,所以有些东西不起作用。错误信息是:期望spy navigate已被调用:[ [ '/error' ] ],但它从未被调用。我该如何解决这个问题?
我的ts代码:

myFunction(): void {
  functionWhichReturnsPromise().then(() => {
    this.router.navigate(['/error']);
  });
}

规范文件:

describe('myComponent', () => {
  let component: myComponent;
  let fixture: ComponentFixture<myComponent>;
  let router: Router;

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

    fixture = TestBed.createComponent(myComponent);
    router = TestBed.inject(Router);
    spyOn('functionWhichReturnsPromise').and.returnValue(Promise.resolve());
    fixture.detectChanges();
  });

  it('should call navigate', () => {
    const spyRouter = spyOn(router, 'navigate').and.resolveTo(true);

    component.myFunction();

    expect(spyRouter).toHaveBeenCalledWith(['/error']);
  });
});
英文:

I'm developing an angular exercising app and testing it with Karma and Jasmine. I'm trying to test router's navigate functionality. The problem is that this call is inside a then(). I suppose something is not working because is async. The error: Expected spy navigate to have been called with:[ [ '/error' ] ] but it was never called. How can I resolve it?
My ts:

  myFunction(): void {
    functionWhichReturnsPromise().then(() =&gt; {
      this.router.navigate(&#39;/error&#39;);
    });
  }

Spec file:

describe(&#39;myComponent&#39;, () =&gt; {
  let component: myComponent;
  let fixture: ComponentFixture&lt;myComponent&gt;;
  let router: Router;

  beforeEach(async () =&gt; {
    await TestBed.configureTestingModule({
      imports: [RouterTestingModule],
      declarations: [myComponent],
      providers: [],
      schemas: [CUSTOM_ELEMENTS_SCHEMA],
    }).compileComponents();

    fixture = TestBed.createComponent(myComponent);
    router = TestBed.inject(Router);
    component = fixture.componentInstance;
    spyOn(&#39;functionWhichReturnsPromise&#39;).and.returnValue(Promise.resolve());
    fixture.detectChanges();
  });

  it(&#39;should call navigate&#39;, () =&gt; {
    const spyRouter = spyOn(router, &#39;navigate&#39;).and.resolveTo(true);

    component.myFunction();

    expect(spyRouter).toHaveBeenCalledWith([&#39;/error&#39;]);
  });
});

答案1

得分: 1

Angular允许您通过将测试函数包装在fakeAsync中,然后使用tick(ms)来同步模拟异步函数的时间流逝,其中ms是您希望经过的毫秒数。

使用您的代码:

 it('should call navigate', fakeAsync(() => {
    const spyRouter = spyOn(router, 'navigate').and.resolveTo(true);

    component.myFunction();
    tick() //可能需要指定毫秒数,具体取决于'myFunction'的操作

    expect(spyRouter).toHaveBeenCalledWith(['/error']);
  }));

FakeAsync文档
请注意,在您的情况下,根据您的Promise的操作,flushMicrotasks()可能也可以代替tick()

英文:

Angular lets you synchronously simulate the passing of time of an async function by wrapping your test function in fakeAsync, then using tick(ms) where ms is the number of millisecond you want ellapsed.

With your code:

 it(&#39;should call navigate&#39;, fakeAsync(() =&gt; {
    const spyRouter = spyOn(router, &#39;navigate&#39;).and.resolveTo(true);

    component.myFunction();
    tick() //might need to specify a number of millisecond 
           //depending on what &#39;myFunction&#39; does

    expect(spyRouter).toHaveBeenCalledWith([&#39;/error&#39;]);
  }));

FakeAsync doc
Note that in you case, depending on what your promise does, flushMicrotasks() might also work instead of tick()

huangapple
  • 本文由 发表于 2023年6月8日 15:18:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/76429458.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定