4

我已经到处找了,但还没有为我的特殊情况找到解决方案。

我们使用 angular 1.5 和 Karma/Jasmine 设置进行单元测试。在最初的源代码中,我在控制器中使用了 ES2017 async/await。只要我在最后手动添加 $apply 的 $digest 似乎就可以正常工作。例如:

async function loadData() {
  try {
    vm.isLoading = true;
    vm.data = await DataService.getData();
    $scope.$apply();
  }
  catch (ex) {
    vm.isLoading = false;
  }
}

为了为这个特定功能编写自动化测试,我尝试使用 Jasmine 模拟 DataService.getData spyOn。所以,我做了这样的事情:

spyOn(DataService, 'getData').and.returnValue($q.when(fakeResult));

添加 spy 有效,但是在运行测试时,代码似乎被击中并且无法使用fakeResult. 我尝试在测试本身中添加 $digest/$apply 但无法修复它。我也做了很多研究,但仍然没有任何线索。

有人有线索吗?

编辑:用$qPromise 测试相同的方法效果很好,但我真的很想使用 async/await ...

4

3 回答 3

1

我不知道您的设置是否相似,但在我们的环境中,我必须做一些事情来获得转译的 async/await 语句以在 jasmine 测试中解决。

  • 在我们的测试中,我试图模拟出会返回承诺的服务。我发现返回$q.when不起作用。相反,我必须返回实际的 A+ 标准 Promises。我的猜测是 Angular 的 $q 承诺并不完全符合标准,也不能作为替代品。

  • 请注意,由于我们使用 PhantomJS 进行测试,因此我必须添加 polyfill 才能获得这些 Promise。

  • 很多时候,在我的测试中,我不得不将一些期望语句包装在一个setTimeout块中。同样,我的假设是承诺需要额外的“滴答”来处理。

于 2017-02-13T21:15:56.883 回答
1

所以没有结果的原因是因为 afterawait没有执行。async/await当我在反应组件内部进行测试时,我遇到了类似的问题。我在某处发现了一种测试方法如下:

  1. 您必须使用类似于https://www.npmjs.com/package/jasmine-async-suite的东西- 这就是我使用的。它适用于您期望得到承诺的异步测试。
    • 还可能存在其他问题,即在 promise 解决后,测试停止,因为没有什么可以等待 :)。这可能非常棘手。
  2. 因此,在您的情况下,您必须手动调用该方法,DataService.getData()并使用该.then()方法,您可以在其中放置您的expect语句 - 由于这一步,您的测试正在等待解决承诺。

这是我的代码示例(我也在async测试中使用函数):

it.async('should call `mySpecialMethod`', async () => {
    const arrayToResolve = [ { data: 'data' } ];
    const SomeService = context.SomeService;

    spyOn(props, 'mySpecialMethod');
    spyOn(SomeService, 'myMethodReturningPromise');
      .and.returnValue(Promise.resolve(arrayToResolve));

    //the method `myMethodReturningPromise` is called in componentDidMount
    const wrapper = mount(<MyReactComponent {...props} />, context);
    expect(SomeService.myMethodReturningPromise).toHaveBeenCalled();

    //now I am calling the method again
    await SomeService.myMethodReturningPromise();

    //`mySpecialMethod` is calling after the `await` in my code
    expect(props.mySpecialMethod).toHaveBeenCalled();
    //after that I am changing the state
    expect(wrapper.state().arrayToResolve).toEqual(arrayToResolve);
});

我希望这可以帮助你 :)

于 2017-02-15T09:26:34.940 回答
0

您可以使用库async-await-jasmine

import * as angular from 'angular';
import 'angular-mocks';
import {yourModule} from "./your-module-path";
import {LoadDataService} from './load-data';
import {$it} from "async-await-jasmine";
import {IRootScopeService} from "angular";


describe('Calculator', () => {
  let $httpBackend: angular.IHttpBackendService;

  beforeEach(() => {
    angular.mock.module(calculatorModule.name);
    angular.mock.inject((_$httpBackend_) => {
      $httpBackend = _$httpBackend_;
    });
  });

  $it('should loadData', async () => {
    $httpBackend.when('GET', '/loadData').respond('{"value": 5}');
    let sum = loadData(1, 4);
    $httpBackend.flush();

    expect(await sum).toBe(10);
  });
});
于 2017-08-03T02:17:02.743 回答