神刀安全网

#5 Testing with Jasmine – async operations

Welcome to the last article about testing with Jasmine framework! In the previous post we discussed spies and today we will focus on async operations . I know, asynchronous code may sound difficult but don’t worry, it is easier than it looks. Ok, let’s get to the point 😉

Testing async operations

Jasmine contains a pretty easy mechanism which allows us to simulate async operations. Let’s see a sample code below:

let calculate = function() {   result 2 + 2; };  describe("a spec", () => {   let calcResult;      beforeEach(done => {     setTimeout(() => {       calcResult = calculate();       done();     }, 3000);   });    it("should wait for until the async operation is finished", () => {     expect(calcResult).toBe(2000000);   }); });

Ok, so we have a calculate function and we want to test it in an asynchronous way. To do so, we call this function in the callback of the setTimeout method. As you can see, we now have to wait 3 seconds until the function will be called. But Jasmine works in a synchronous way so the it function will be called before the calcResult is set.

To avoid this, we can pass a done callback function and call it after the async operation is finished. In our example we used it in the beforeEach function but you can also pass it to the beforeAll , afterAll , afterEach and it functions. When we pass this callback, Jasmine will know that it has to wait and will postpone all further tests until the done callback is called.

Timeouts

By default, Jasmine waits 5 seconds for the done function call. If the timeout is exceeded the test is marked as failed.

If you know that your async operation will take more than 5 seconds, you can pass a second parameter – please see the example below:

beforeEach(done => {   setTimeout(() => {     calcResult = calculate();     done();   }, 3000); }, 8000);

This way we increase the timeout to 8 seconds.

But what if you want to increase the timeout for the whole test suite? You can set it globally by setting the value of jasmine.DEFAULT_TIMEOUT_INTERVAL .

How to mock an AJAX call?

Many times in our specs we don’t want to test async operations as presented above. Instead, we just want to mock the async behaviour. One of the most common situations we may want to test is an AJAX call, for example using a jQuery library. The most typical AJAX call using jQuery is similar to the one below:

$.when($.ajax('remote url', parameters))   .then(() => {     // success   });

Ok, so let’s imagine the function which uses the above approach to search cars by id:

let car; let searchCar(id) {   $.when($.ajax('/cars/get', id))     .then((response) => {       car = response;     });   } }

I bet that if you see the construction similar to when ... then ... you know that we are using promises here, right? Exactly! So to mock the above function we will use promises as well:

describe('search for the car', () => {   beforeEach(() => {     const deferred = $.Deferred();     deferred.resolve('Volvo');          spyOn($, 'ajax').and.returnValue(deferred.promise());   });    it('should return a correct result', () => {     // act     searchCar(5);          // assert     expect(car).toBe('Volvo');   }); });

As you can see, this approach is pretty simple: we just created a Deferred object, resolved it and then used “spy” (if you are not familiar with it, check out my previous post ) to mock the returned value of the ajax function by the Deferred object’s promise.

Of course I’ve used jQuery only as an example! You can use your favourite promises implementation instead.

Summary

That’s all for today and for the whole “Testing with Jasmine” series. I hope it will be helpful for some of you and you are now convinced that it is not so complicated to write unit tests in JavaScript. There are many test frameworks on the market but I think Jasmine is really easy to learn so it’s a good start for everyone who wants to write their first test!

转载本站任何文章请注明:转载至神刀安全网,谢谢神刀安全网 » #5 Testing with Jasmine – async operations

分享到:更多 ()

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
分享按钮