Testing asynchronous functionality in Jasmine 2.0.0 with done ()

I am trying to implement a jasmine test on a simple promise implementation (asynchronous code) with a done () function, and my test fails, although the tested code works fine. Can someone help me figure out what is missing in my test?

var Test = (function () { function Test(fn) { this.tool = null; fn(this.resolve.bind(this)); } Test.prototype.then = function (cb) { this.callback = cb; }; Test.prototype.resolve = function (value) { var me = this; setTimeout(function () { me.callback(value); }, 5000); }; return Test; })(); describe("setTimeout", function () { var test, newValue = false, originalTimeout; beforeEach(function (done) { originalTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL; jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000; test = new Test(function (cb) { setTimeout(function () { cb(); }, 5000); }); test.then(function () { newValue = true; console.log(1, newValue); done(); }); }); it("Should be true", function (done) { expect(1).toBe(1); expect(newValue).toBeTruthy(); }); afterEach(function () { jasmine.DEFAULT_TIMEOUT_INTERVAL = originalTimeout; }); }); 

same test in jsfiddle: http://jsfiddle.net/ravitb/zsachqpg/

+7
asynchronous jasmine
source share
1 answer

This code is testing a simple promise-like object, so it will call the Test object for convenience.

After creating a promise, there are two different asynchronous events: 1. Calling the .then() method 2. Solving the promise by calling the cb() function in the beforeEach() function.

In the real world, these two can be called in any order and at any time.

For the test, the call to .then() must be transferred to the callback of the it() section, and all specification methods (e.g. expect() ) must be called in this callback or they will be executed before it is resolved. beforeEach() is part of the test setup, and the it() function is the specification, the test itself.

The done() method needs to be called twice,

  • When the async beforeEach() action is completed (i.e. after calling cb() ), this will trigger the specification. Therefore, it should look something like this:

      beforeEach(function (done) { test = new Test(function (cb) { setTimeout(function () { console.log("in beforeEach() | setTimeout()"); cb(resolvedValue); done() }, 500); }); }); 
  • When the async action in spec ( it() ) is completed inside the .then() method after all calls to the jasmine test methods, it will say that the Jasmine spec has finished (and thus the timeout won 't). So:

     it("Should be " + resolvedValue, function (done) { test.then(function (value) { console.log("in then()"); expect(value).toBe(resolvedValue); done(); }); }); 

In addition, as you can see, instead of checking that the value of the variable has changed, I check that the value passed to the .then() method matches the one that was passed to the promise resolution function cb() , as this is the correct behavior. which you expect.

Here is the updated version of your violin.

You can check the browser console to see that all callbacks are being called

Note. Changing Jasmine's DEFAULT_TIMEOUT_INTERVAL just makes it more confusing for no reason, so I deleted it and extraneous code.

+7
source share

All Articles