【问题标题】:AngularJS unit testing: using async/await with JasmineAngularJS 单元测试:使用 async/await 和 Jasmine
【发布时间】:2018-01-06 06:16:57
【问题描述】:

我正在尝试在下面的相应 (Jasmine) 单元测试中使用 async/await 关键字对我的 Angular 服务进行单元测试。原生 Promise 的测试工作正常,但我几乎坚持让 Angular $q 对应工作。

  • 角度:1.6.5
  • 茉莉花:2.7.0
  • (无头)MacOS 上的 Chrome:60.x

angular
  .module('asyncAwaitTest', [])
  .factory('xService', xServiceFactory);

function xServiceFactory(
  $q,
  $timeout
) {
  return {
    getXAfter1Sec() {
      return new Promise(resolve => setTimeout(() => resolve(43), 1000));
    },
    getXAfter1SecWithAngular$Q() {
      const deferred = $q.defer();

      $timeout(() => deferred.resolve(43), 1000);

      return deferred.promise;
    }
  };
}

jasmine.DEFAULT_TIMEOUT_INTERVAL = 2000;

describe('asyncAwaitTest: x service', () => {
  let $timeout;
  let xService;

  beforeEach(() => {
    module('asyncAwaitTest');

    inject(
      (
        _$timeout_,
        _xService_
      ) => {
        $timeout = _$timeout_;
        xService = _xService_;
      }
    );
  });

  it('should work', async (done) => {
    const x = await xService.getXAfter1Sec();

    expect(x).toEqual(43);

    done();
  });

  it('should work, too. but y not?!!', async (done) => {
    const xPromise = xService.getXAfter1SecWithAngular$Q();

    $timeout.flush();

    const x = await xPromise;

    expect(x).toEqual(43);

    done();
  });
});

此处提供小提琴:https://jsfiddle.net/glenn/gaoh6bvc/

我已经尝试过 Google,但它并没有给我带来显着的领先优势????

【问题讨论】:

  • async/await 不知道$q。他们使用原生承诺。看看这个:stackoverflow.com/questions/35629246/…
  • 我明白了。但是有什么解决方法吗?将.run(function runBlock($window, $q) { $window.Promise = $q; }); 放在只会让情况变得更糟——这两项测试都失败了:/

标签: javascript angularjs unit-testing jasmine async-await


【解决方案1】:

您可以为您的测试创建一个助手,将 Promise 从 $q 转换为原生 Promise。看看here。

it('should work, too. but y not?!!', async (done) => {
  const xPromise = toNativePromise(xService.getXAfter1SecWithAngular$Q());

  $timeout.flush();

  const x = await xPromise;

  expect(x).toEqual(43);

  done();
});

function toNativePromise(promise) {
  return new Promise((resolve, reject) => {
    promise.then(val => {
      resolve(val);
    }, err => {
      reject(err);
    });
  });
}

【讨论】:

  • 我认为这是目前可以接受的解决方法。谢谢! :)
【解决方案2】:

async 函数基于原生承诺,而 AngularJS 使用 $q 承诺。 await 是一种语法糖,用于将 promise 与 then 链接起来。 $q 承诺链在测试中的摘要上执行。

这个不能用

修复
await xPromise;
$rootScope.$digest();

因为 $rootScope.$digest() 在执行 $rootScope.$digest() 之前不会被评估。这会导致未决的承诺。

AngularJS 首先不应该使用async..await 进行测试。 Angular 被设计为同步测试。

是

it('...', () => {
  ...
  xPromise.then(x => {
    expect(x).toEqual(43);
  });
  $rootScope.$digest();
});

或者可以使用jasmine-promise-matchers 扁平化承诺:

it('...', () => {
  ...
  expect(xPromise).toBeResolvedWith(43);
  $rootScope.$digest();
});

【讨论】:

    猜你喜欢
    • 2013-08-29
    • 2013-06-29
    • 1970-01-01
    • 1970-01-01
    • 2014-01-11
    • 1970-01-01
    • 2016-07-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多