Why is using jasmine's runs and waitFor function necessary?

爱⌒轻易说出口 提交于 2019-12-11 11:16:29

问题


I'm testing an asynchronous piece of code with something that looks like this:

randomService.doSomething().then(function() {
    console.log('I completed the operation!');
});

Surprisingly (to me) I've found that it only succeeds (ie console.log output is shown) when wrapped inside jasmine's runs function, like so:

var isDone = false;

runs(function() {
    randomService.doSomething().then(function(data) {
        console.log('I completed the operation!');
        isDone = true;
    });
});

waitsFor(function() {
    return isDone;
}, 'Operation should be completed', 1000);

As I understood it, I thought waitsFor was only to delay the code, in other words I would use it if I had more code that I had to delay until after the asynchronous call completed - in other words, I would have thought that there'd be no reason for me to use runs and waitsFor since there's nothing that comes after this bit of code, right? That's the impression I got from reading this question: What do jasmine runs and waitsFor actually do? but obviously I've gotten myself mixed up at some point.

Does anyone have any thoughts on this?


EDIT: Here is a Plunker with far more detail of the problem: http://plnkr.co/edit/3qnuj5N9Thb2UdgoxYaD?p=preview

Note how the first test always passes, and the second test fails as it should. Also, I'm sure I should have mentioned this before, but this is using angularJS, and Jasmine 1.3.


回答1:


I think I found the issue. Here's the article: http://blogs.lessthandot.com/index.php/webdev/uidevelopment/javascript/testing-asynchronous-javascript-w-jasmine/

Essentially it's necessary because Jasmine doesn't wait for the asynchronous calls to finish before it completes a test. According to the article, if a call takes long enough and there are more tests later, an expect statement in an asynchronous callback in a previous test could finally execute in a different test entirely, after the original test completed.

Using runs and waitsFor solve the problem because they force jasmine to wait for the waitsFor to finish before proceeding to the next test; This is a moot point however because evidently Jasmine 2.0 addresses asynchronous testing in a better way than 1.3, obsoleting runs and waitsFor.




回答2:


That's just how Jasmine works. The question you linked has an answer with a decent explanation:

Essentially, the runs() and waitFor() functions stuff an array with their provided functions. The array is then processed by jamine wherein the functions are invoked sequentially. Those functions registered by runs() are expected to perform actual work while those registered by waitFor() are expected to be 'latch' functions and will be polled (invoked) every 10ms until they return true or the optional registered timeout period expires. If the timeout period expires an error is reported using the optional registered error message; otherwise, the process continues with the next function in the array.

To sum it up, each waitsFor call must have a corresponding runs call. They work together. Calling waitsFor without a runs call somewhere before it does not make sense.


My revised plunker (see comments on this answer): http://plnkr.co/edit/9eL9d9uERre4Q17lWQmw

As you can see, I added $rootScope.$apply(); to the the timeout function you were testing with. This makes the console.log inside the promise callback run. HOWEVER it only runs if you ignore the other test with an xit, AND the expect after the console.log does not seem to be recognized as a Jasmine test (though it certainly must run, because the console.log does).

Very weird - I don't really understand why this is happening, but I think it has something to do with how Jasmine works behind the scenes, how it registers tests and whatnot. My understanding at this point is if you have an expect inside an async callback, Jasmine won't "recognize" it as a part of the test suite unless the initial async call was made inside a runs.

As for why this is, I don't know. I don't think it's worth trying to understand - I would just use runs and waitsFor and not worry about it, but that's just me. You can always dig through the source if you're feeling masochistic. Sorry I couldn't be of more help.



来源:https://stackoverflow.com/questions/24619664/why-is-using-jasmines-runs-and-waitfor-function-necessary

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!