Angular 测试预期间谍 navigateByUrl 已被调用 0 次。它被调用了 1 次

Angular testing Expected spy navigateByUrl to have been called 0 times. It was called 1 times

我在使用 Karma/Jasmine.

测试基于 Angular RxJS 的函数时有一个奇怪的行为

我有这个测试:

describe('LoginComponent', () => {
  let fixture: ComponentFixture<LoginComponent>;
  let component: LoginComponent;
  let debugElement: DebugElement;
  let location: Location;
  let router: Router;
  let authServiceSpy: AuthService = {
    login: () => null,
    user: new BehaviorSubject<UserInterface>(null)
  } as jasmine.SpyObj<any>;

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      imports: [
        HttpClientTestingModule,
        RouterTestingModule,
        AppModule,
      ],
      providers: [
        { provide: AuthService, useValue: authServiceSpy },
      ],
      declarations: [
        LoginComponent,
      ]
    })
    .compileComponents()
    .then(() => {
      router = TestBed.inject(Router);
      location = TestBed.inject(Location);
      fixture = TestBed.createComponent(LoginComponent);
      component = fixture.componentInstance;
      debugElement = fixture.debugElement;
    });
  });

  describe('submit form', () => {
    it('should navigate to dashboard with correct credentials', fakeAsync(() => {
      spyOn(authServiceSpy, 'login').and.returnValue(of(new User()));
      const navSpy = spyOn(router, 'navigateByUrl');
      const button = debugElement.queryAll(By.css('.login-button'));
      fixture.detectChanges();
      fixture.whenStable().then(() => {
        button[0].nativeElement.click();
        tick();
        expect(navSpy).toHaveBeenCalledTimes(1);
        expect(navSpy).toHaveBeenCalledWith('/dashboard');
      });
    }));

    it('should show error with incorrect credentials', fakeAsync(() => {
      spyOn(authServiceSpy, 'login').and.returnValue(throwError('login failed'));
      const navSpy = spyOn(router, 'navigateByUrl');
      const button = debugElement.queryAll(By.css('.login-button'));

      fixture.detectChanges();
      fixture.whenStable().then(() => {
        button[0].nativeElement.click();
        tick();
        fixture.detectChanges();

        expect(navSpy).toHaveBeenCalledTimes(0);
      });
    }));
  });
});

经过 运行 这些测试后,我收到此错误消息:

Error: 1 timer(s) still in the queue.

然后我添加 flush() 作为两个 it() 函数的开始。我得到这个错误:

Expected spy navigateByUrl to have been called 0 times. It was called 1 times.

我也尝试使用 discardPeriodicTasks()flushMicrotasks()。但没有帮助。

当我将 it() 功能与 fit() 一个接一个地使用时,一切正常。

知道如何解决这个问题吗?

正如@rmjoia所指出的,您需要重置间谍对象,因为它将在相关测试规范中重复使用。 可以通过 reset method.

来完成重置

navSpy.calls.reset

我建议在 beforeEach 函数上执行此操作。

另一个解决方案是将测试分成两个测试套件