睡在茉莉花

Pha*_*gun 3 jasmine angularjs

用例:对于我的 angularJS(1.6.4) 应用程序,我正在用 jasmine 编写单元测试。

在我的测试用例中,我调用了一个 poll() 函数,该函数不断使用 $interval 重复调用另一个函数 CheckTaskStatus()。我正在监视 CheckTaskStatus() 并想检查它是否被调用了一定次数。所以在调用 poll() 之后,我希望能够等待一段时间,然后检查使用 expect() 调用 CheckTaskStatus() 的次数。

问题:我一直无法找到一种方法让 jasmine 在调用 poll() 之后和 expect() 之前等待。

在 poll() 之后,我尝试使用以下选项,但这些选项不会导致茉莉花入睡:

  • $超时
  • 设置超时
  • 异步函数调用 await 函数返回承诺。 服务 导入 * 作为 'angular' 的角度;

导出类轮询 { public static $inject = ['$q', '$http', '$interval'];

constructor(private $q: ng.IQService, private $http, private $interval) {}

public poll(interval: number, pollFn: () => ng.IPromise<any>, until?: (any) => boolean, cancel?: ng.IPromise<any>) {
    let intervalPromise = null;
    const done = this.$q.defer();

    const intervalFn = () => {
        pollFn().then((pollFnResult) => {
            if (until && until(pollFnResult)) {
                this.$interval.cancel(intervalPromise);
                done.resolve();
            }
        }).catch(() => {});  
    };

    // Set up an interval to execute the pollFunction
    intervalPromise = this.$interval(intervalFn, interval);
    intervalPromise.catch(() => {});

    intervalFn();

    if (cancel) {
        cancel.then(() => {
            this.$interval.cancel(intervalPromise);
            done.resolve();
        })
            .catch(() => {}); 
    }

    return done.promise;
}
Run Code Online (Sandbox Code Playgroud)

}

导出默认 angular.module('myPolling', []) .service('polling', Polling).name;

茉莉花测试

constructor(private $q: ng.IQService, private $http, private $interval) {}

public poll(interval: number, pollFn: () => ng.IPromise<any>, until?: (any) => boolean, cancel?: ng.IPromise<any>) {
    let intervalPromise = null;
    const done = this.$q.defer();

    const intervalFn = () => {
        pollFn().then((pollFnResult) => {
            if (until && until(pollFnResult)) {
                this.$interval.cancel(intervalPromise);
                done.resolve();
            }
        }).catch(() => {});  
    };

    // Set up an interval to execute the pollFunction
    intervalPromise = this.$interval(intervalFn, interval);
    intervalPromise.catch(() => {});

    intervalFn();

    if (cancel) {
        cancel.then(() => {
            this.$interval.cancel(intervalPromise);
            done.resolve();
        })
            .catch(() => {}); 
    }

    return done.promise;
}
Run Code Online (Sandbox Code Playgroud)

Est*_*ask 5

AngularJS 异步代码和任意 JS 代码在 Jasmine 中的测试方式不同。

AngularJS 服务是专门为使测试同步而设计的,包括$interval

在测试中,您可以使用 $interval.flush(millis) 以毫秒为单位向前移动并触发计划在该时间内运行的任何函数。

所以它是:

let cancel = this.$q.defer();
this.polling.poll(100, pollObj.pollFn, () => false, cancel.promise);

$interval.flush(1050);
expect(pollObj.pollFn).toHaveBeenCalledTimes(10);
Run Code Online (Sandbox Code Playgroud)

在涉及非 Angular 异步单元的测试中是不同的。应该使用Jasmine 时钟 API。它修补内置计时器功能,以便与 Jasminetick方法同步执行它们。

beforeEach(() => {
  jasmine.clock().install();
});

afterEach(() => {
  jasmine.clock().uninstall();
});

it('...', () => {
  SleepForASecond().then(() => {
    expect(1).toBe(0);
  });
  jasmine.clock().tick(1050);
});
Run Code Online (Sandbox Code Playgroud)

Jasmine 2.7添加了对 promise 和async函数的支持。这允许无缝测试基于承诺的功能,但承诺会产生真正的延迟并导致异步测试:

it('...', async () => {
  await SleepForASecond();
  expect(1).toBe(0);
});
Run Code Online (Sandbox Code Playgroud)