2

I'm trying to do some test with Jasmine and RequireJS. Everything was going really well until I noticed that I had a problem regarding the context of the functions I was describing.

I'm doing some Ajax test so, the first thing I do is to set up a listener for the success, then requesting that service. Then, inside each of my it() declarations I do my tests based on the service response.

Here are my spec modules:

// auth.js
define(['service/auth'], function(auth) {
  describe('Tests "auth" service', function() {
    var data;
    var OPTIONS = {
      CN: '147144147',
      GV: '147153162'
    };

    auth.on.success.addOnce(function(response) {
      data = response;
    });

    auth.request(OPTIONS);

    it('"status" should exist and be "true"', function() {
      waitsFor(function() {
        return data !== undefined;
      });

      runs(function() {
        expect(data['status']).toBeDefined();
        expect(data['status']).toBeTruthy();
      });
    });

  });
});

// login.js
define(['service/login'], function(login) {
  describe('Tests "login" service', function() {
    var data;
    var OPTIONS = {
      oper: 1,
      codigoouemail: '101',
      senha: '10151015'
    };

    login.on.success.addOnce(function( response ) {
      data = response;
    });

    login.request(OPTIONS);

    it('Should get the service response for user "' + OPTIONS.codigoouemail + '"', function() {
      waitsFor(function() {
        return data !== undefined;
      });

      runs(function() {
        expect(data).toBeDefined();
      });
    });

  });
});

They both work fine when tested individually but what I noticed is that they share the same value for data. The first module to run, sets its value and the other specs will have the same value. I need to have a single value per module so I can test each service response properly. In theory, every module should have its own scope but doesn't look like this is happening.

Someone have any idea on how to solve this?

  • On a side note, [Jasmine 2.0.0](http://jasmine.github.io/2.0/introduction.html) now has an optional `done` parameter for the `it()` method that allows you write async tests with a little less code. Also note, however, that if you're using [Karma test runner](http://karma-runner.github.io/0.10/index.html), [Karma currently comes bundled with Jasmine 1.3.1](http://stackoverflow.com/a/21117832/456814), so you wouldn't be able to use the new `done` parameter in that case (at least until Karma updates its version of Jasmine). –  Feb 05 '14 at 05:52
  • [Testing Asynchronous Javascript w/ Jasmine 2.0.0](http://blogs.lessthandot.com/index.php/webdev/uidevelopment/javascript/testing-asynchronous-javascript-w-jasmine/) is a good blog post on how to use the new Jasmine 2.0.0 `done` parameter, if you have that version of Jasmine available. –  Feb 05 '14 at 05:55
  • @Cupcake Oh, finally! Great stuff. I'm currently running tests with Konacha plus Sinon and Chai. I have to give Jasmine another chance :) –  Feb 11 '14 at 16:07

3 Answers3

1

So here's an example of an async test I use to check if my VOs are created:

it('should return a list of item VOs', function() {
  var dfd = $q.defer();
  var items = mock.content.items[1].items;

  runs(function() {
    dfd.promise.then(function(VOs) {
      expect(VOs.length).toBe(items.length);
      expect(A.equals(itemVO(items[0]), VOs[0])).toBe(true);
    }, this.fail);
  });

  waits(50);

  runs(function() {
    itemsVO(dfd, items);

    $rootScope.$digest();
  });
});

So first I run a function to listen to when my async function has completed, I wait 50ms to check that the app is ready and then I run my async function. Notice how the expect is in the callback.

Ahmed Nuaman
  • 12,662
  • 15
  • 55
  • 87
1

So this was totally my bad. It was an error on the ajax call, which was giving me always the same value and therefore failing all the tests. Thanks for the help anyway :)

0

Sorry to say, but the problem is not in the data variable. Javascript has function scope, so the two data variables are different. Here's a fiddle showing that data is not the same: http://jsfiddle.net/LNuHU/2/

Below is the code:

//--- SPECS -------------------------
describe('Tests timeout service 1', function() {

        var data;

        setTimeout(function( response ) {
            data = 3;
        }, 1000);


        it('Should be 3', function() {

            waitsFor(function() {
                return data !== undefined;
            });

            runs(function() {
                expect(data).toBe(3);
            });

        });


        it('Should be 30', function() {

            waitsFor(function() {
                return data === 30;
            });

            runs(function() {
                expect(data).toBe(30);
            });

        });

    });

describe('Tests timeout service 2', function() {

        var data;

        setTimeout(function( response ) {
            data = 30;
        }, 2000);


        it('Should be 30', function() {

            waitsFor(function() {
                return data !== undefined;
            });

            runs(function() {
                expect(data).toBe(30);
            });

        });


        it('Should be 30', function() {

            waitsFor(function() {
                return data === 3;
            });

            runs(function() {
                expect(data).toBe(3);
            });

        });

    });
John Tseng
  • 6,262
  • 2
  • 27
  • 35
  • Yeah, I know that. What bothers me is that RequireJS is supposed to handle function scoping (and it does that really well). So I'm assuming the issue is on Jasmine not playing well with async code regarding function context. I even found some people with the same problem... –  Jul 01 '13 at 05:33
  • Hey man, now I see what you did here... `data` has a different value per `describe()` which is exactly what I want, but why don't I get the same result? When I print the `data` value it's always the value of the first `response`. This is annoying me so bad... –  Jul 01 '13 at 14:50