【问题标题】:Angular - How to test setInteval with JasmineAngular - 如何使用 Jasmine 测试 setInterval
【发布时间】:2021-11-25 08:24:51
【问题描述】:

我正在使用 Angular 11 的应用程序。

我有一个 loginService,允许用户与他们的个人资料进行交互。 在我的应用程序中有 jwt 身份验证,并且每 30 分钟刷新一次令牌。

我的 LoginService 如下所示

@Injectable()
export class LoginService {

    private intervalId: any;

    constructor(private readonly http: HttpClient,
                private readonly ngZone: NgZone) {
        this.ngZone.runOutsideAngular(() => {

            this.intervalId = setInterval(() => {
                ngZone.run(() => {
                    this.renewJwtToken();
                });
            }, 1000 * 60 * 30);
        });
    }

    callLogin(loginRequest: LoginRequest): Observable<HttpResponse<LoginResponse>> {
        // call in order to login user
    }

    renewJwtToken() {
        // call in order to renew the token
    }
}

我的问题在于浅层测试(我们在其中创建 TestBed)。我正在使用 jasmine 3.8 和 karma 6.3.4

每个测试都返回以下错误

Error: Timeout - Async function did not complete within 5000ms (set by jasmine.DEFAULT_TIMEOUT_INTERVAL)
            at <Jasmine>

如果我注释 LoginService 构造函数的内容,一切正常。

如何在不禁用 LoginService 构造函数中的 setInterval 的情况下测试我的应用程序?

谢谢

【问题讨论】:

    标签: angular jasmine karma-jasmine


    【解决方案1】:

    看看fakeAsyncflush 是否会帮助你(https://stackoverflow.com/a/53864251/7365461)。 fakeAsynctick 将允许您手动推进时间,tick 不带参数将允许您确保所有承诺都已完成(与 flushMicroTasks() 相同)但超时和间隔是宏任务并查看 flush fakeAsync 区域内的命令可以帮助您。

    我认为由于您的 setInterval 在构造函数中,请确保您的 service = TestBed.inject(LoginService); 也在 fakeAsync 区域中。

    类似这样的:

    import { fakeAsync, flush } from '@angular/core/testing';
    ....
    beforeEach(fakeAsync(() => {
        service = TestBed.inject(LoginService);
        flush();
    }));
    

    runOutsideAngular 中运行的代码可能会导致复杂性,因此您可以考虑为setInterval 创建一个可重用的服务,然后在您的测试中模拟它。看看这个link

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-11-12
      • 1970-01-01
      • 2022-01-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多