本文介绍了为什么我在Jasmine 1.3.x中的AngularJS异步测试不起作用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

您好我有一个使用AngularJS(1.5.11)编写的功能完整的网络应用程序,现在我开始使用业力(0.12.37),grunt-karma(0.8.3),karma-chrome进行单元测试-launcher(0.1.12),karma-phantomjs-launcher(1.0.4), phantomjs-prebuilt (2.1.14),jasmine-promise-matchers(2.3.0)和karma-jasmine( 0.1.6),1.3.x Jasmine版本。

Hi I have a feature complete web-app written using AngularJS (1.5.11) and now I'm getting started with unit testing using karma (0.12.37), grunt-karma (0.8.3), karma-chrome-launcher (0.1.12), karma-phantomjs-launcher (1.0.4), phantomjs-prebuilt (2.1.14), jasmine-promise-matchers (2.3.0) and karma-jasmine (0.1.6), with a 1.3.x Jasmine version.

我对测试异步内容不是很有信心,所以我开始在Google上搜索,我总是看到在调用异步函数之后,运行AngularJS异步测试的唯一必要条件是 $ rootScope / $ scope。$ apply / $ digest

I'm not very confident in testing asynchronous stuff, so I started googling around and I always end up seeing the only mandatory thing to run AngularJS async tests is a $rootScope/$scope.$apply/$digest right after the async function has been called.

最终我发现并在此特别顺畅,但在使用phantomjs-launcher时失败,抛出如下错误:

Eventually I found someone suggesting me to use runs() and waitsFor() and the test in this plunkr in particular runs smoothly when using the chrome-launcher but fails when using phantomjs-launcher, throwing an error like the following:

Expected { myError : { error : 'error_message' }, line : <factory's line of code which throws the error>, sourceURL : 'path/to/factory.js', stack :

     <function throwing error> B@path/to/factory.js:<factory's line of code which throws the error>
     <"async" function> A@path/to/factory.js:<factory's line of code which calls B()>
     path/to/factory-spec.js:<the following line of code: var promise = HandleService.A();>
     invoke@path/to/angular/angular.js:4771:24
     WorkFn@path/to/angular-mocks/angular-mocks.js:3130:26
     execute@path/to/node_modules/karma-jasmine/lib/jasmine.js:1145:22
     next_@path/to/node_modules/karma-jasmine/lib/jasmine.js:2177:38
     start@path/to/node_modules/karma-jasmine/lib/jasmine.js:2130:13
     execute@path/to/node_modules/karma-jasmine/lib/jasmine.js:2458:19
     next_@path/to/node_modules/karma-jasmine/lib/jasmine.js:2177:38
     start@path/to/node_modules/karma-jasmine/lib/jasmine.js:2130:13
     execute@path/to/node_modules/karma-jasmine/lib/jasmine.js:2604:19
     next_@path/to/node_modules/karma-jasmine/lib/jasmine.js:2177:38
     start@path/to/node_modules/karma-jasmine/lib/jasmine.js:2130:13
     execute@path/to/node_modules/karma-jasmine/lib/jasmine.js:2604:19
     next_@path/to/node_modules/karma-jasmine/lib/jasmine.js:2177:38
     onComplete@path/to/node_modules/karma-jasmine/lib/jasmine.js:2173:23
     finish@path/to/node_modules/karma-jasmine/lib/jasmine.js:2561:15
     path/to/node_modules/karma-jasmine/lib/jasmine.js:2605:16

     next_@path/to/node_modules/karma-jasmine/lib/jasmine.js:2187:24
     onComplete@path/to/node_modules/karma-jasmine/lib/jasmine.js:2173:23
     finish@path/to/node_modules/karma-jasmine/lib/jasmine.js:2561:15
     path/to/node_modules/karma-jasmine/lib/jasmine.js:2605:16

     next_@path/to/node_modules/karma-jasmine/lib/jasmine.js:2187:24
     onComplete@path/to/node_modules/karma-jasmine/lib/jasmine.js:2173:23
     finish@path/to/node_modules/karma-jasmine/lib/jasmine.js:2432:15
     path/to/node_modules/karma-jasmine/lib/jasmine.js:2459:16

     next_@path/to/node_modules/karma-jasmine/lib/jasmine.js:2187:24
     path/to/node_modules/karma-jasmine/lib/jasmine.js:2167:23' }, pending : undefined, processScheduled : false } } to be rejected with { myError : { error : 'error_message' } }.

所以我开始认为Chrome结果是误报,我需要重写异步测试:因此我试过这样的,但现在PhantomJs和Chrome中的测试都失败了与预期的超时消息:

So I started to think Chrome results were false positive, and I needed to rewrite the async tests: hence I tried with something like this plunkr, but now the tests fail both in PhantomJs and Chrome with the expected timeout message:

timeout: timed out after 1500 msec waiting for A should catch an error

NB: 我无法将Jasmine更新为2.0版并使用完成参数机制现在如果我做对了,我甚至不应该手动触发 $ rootScope。$ apply / $ digest 使用时。

N.B.: I can't update Jasmine to version 2.0 and use the done parameter mechanism now and if I got it right I should not even manually trigger a $rootScope.$apply/$digest when using jasmine-promise-matchers.

推荐答案

Angular'async'测试通常是同步的,因此 waitsFor 运行是不必要的,显然有害。

Angular 'async' tests are generally synchronous, thus waitsFor and runs are unnecessary and apparently harmful.

确实, jasmine-promise-matchers 不需要手动触发摘要来执行$ q promises,因为这是在内部完成的。

Indeed, jasmine-promise-matchers don't need to trigger a digest manually to execute $q promises since this is done internally.

这里的问题是竞争条件。第一个运行似乎在 $ rootScope。$ digest()之后运行,而 catch 块永远不会被执行 - 所以是第二个运行

The problem here is race condition. First runs seems to run after $rootScope.$digest(), and catch block is never executed - so is second runs.

相反,它应该同步测试:

Instead, it should be tested synchronously:

  it('it actually throws an error, yay', function () {
    var promise = HandleService.A();

    expect(promise).toBePromise();
    expect(promise).toBeRejectedWith(jasmine.objectContaining({
      myError: {error: 'error_message'}
    }));
  });

这篇关于为什么我在Jasmine 1.3.x中的AngularJS异步测试不起作用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-27 13:25