user2112618
user2112618

Reputation: 346

Jasmine checking if variable is defined in method

I'm new to jasmine. My Company is using jasmine 1.3.1

I am trying to test if a variable is defined in a method. I keep coming back with a failure.

objectParentName.accessoriesSlider = {
modifyJSON: function(obj) {
        var contentLoadJSON = [];

        for (var property in obj) {
            objectParentName.accessoriesSlider.contentJSONTotal++
            contentLoadJSON.push(obj[property]);
        }

        contentLoadJSON = objectParentName.accessoriesSlider.sortJSON(contentLoadJSON, 'dateAdded', false);

        return contentLoadJSON;
    }
}

Here is jasmine for that method.

describe('Test "modifyJSON" function', function () {

    beforeEach(function() {
        spyOn(objectParentName.accessoriesSlider, 'modifyJSON');

        var contentLoadJSON = []; //forcibly add variable to see if that fixes issue
        objectParentName.accessoriesSlider.modifyJSON();
    });

    it('is defined as "modifyJSON"', function () {
        /**
         * objectParentName.accessoriesSlider.modifyJSON should be defined.
         */

        expect(objectParentName.accessoriesSlider.modifyJSON).toBeDefined();
    });

    it('and "modifyJSON" is a function', function () {
        /**
         * This should be a 'function'.
         */

        expect(objectParentName.accessoriesSlider.modifyJSON).toBeFunction();
    });

    describe('Test "contentLoadJSON" variable', function () {
        it('is defined', function () {
            expect(contentLoadJSON).toBeDefined();
        });

    });

});

I am getting this error

ReferenceError: contentLoadJSON is not defined
at .<anonymous> (http://localhost:8234/spec/jasmine_accessories_slider.js:300:24)
at jasmine.Block.execute (http://localhost:8234/?spec=accessories_slider.js:1164:19)
at jasmine.Queue.next_ (http://localhost:8234/?spec=accessories_slider.js:2196:33)
at jasmine.Queue.start (http://localhost:8234/?spec=accessories_slider.js:2149:10)
at jasmine.Spec.execute (http://localhost:8234/?spec=accessories_slider.js:2476:16)
at jasmine.Queue.next_ (http://localhost:8234/?spec=accessories_slider.js:2196:33)
at jasmine.Queue.start (http://localhost:8234/?spec=accessories_slider.js:2149:10)
at jasmine.Suite.execute (http://localhost:8234/?spec=accessories_slider.js:2621:16)
at jasmine.Queue.next_ (http://localhost:8234/?spec=accessories_slider.js:2196:33)
at jasmine.Queue.start (http://localhost:8234/?spec=accessories_slider.js:2149:10)

So, I have no idea why I am getting an error here.

Upvotes: 2

Views: 5303

Answers (1)

Merlyn Morgan-Graham
Merlyn Morgan-Graham

Reputation: 59151

The first problem is that the variable contentLoadJSON is not defined in the scope of the function you are calling it from.

When you define a variable using var, it becomes a local variable, and is only accessible inside the scope of that function. In this case, the function it exists in is:

beforeEach(function() {
    spyOn(objectParentName.accessoriesSlider, 'modifyJSON');

    var contentLoadJSON = [];

    objectParentName.accessoriesSlider.modifyJSON();
});

The function you are getting the error in is a different function() { ... } that isn't nested in beforeEach. It is therefore can't see the local variable you defined.

One way to rectify this is by defining the variable in the scope of your test suite, instead of in the scope of the beforeEach function:

describe('Test "modifyJSON" function', function () {
    var contentLoadJSON; // Define it here

    beforeEach(function() {
        contentLoadJSON = []; // Assign it here
        // ... more code here ...
    }

    // ... more code here ...

    describe('Test "contentLoadJSON" variable', function () {
        it('is defined', function () {
            // Test contentLoadJSON here...

The second problem is that just because variables have the same name doesn't mean they are actually the same variable. They have to also be in the same scope for that to be true. var contentLoadJSON inside modifyJSON is actually a totally different variable than the var contentLoadJSON you are defining in beforeEach in your test suite.

When you call the function under test, you are not assigning its result to the variable you are trying to test. In fact, you are actually throwing away the result immediately after you call the function.

To fix this, change:

var contentLoadJSON = [];
objectParentName.accessoriesSlider.modifyJSON();
// Note that contentLoadJSON still equals [] at this point.
// The return of the function call is getting thrown away,
// because you don't assign it to a variable

To:

var contentLoadJSON = objectParentName.accessoriesSlider.modifyJSON();

The third problem is that expect(someVariable).toBeDefined(); might not do what you are expecting it to do. It doesn't check that the variable is "in scope". It checks that the value someVariable is not equal to the value undefined. Unless your function might sometimes return undefined, then this particular test isn't very important and will probably never fail.

It may be better to check that the result is "truthy" (expect(contentLoadJSON).toBeTruthy()). It might even make sense to just check that it is equal to the value you'd expect for the given data/input.

Upvotes: 2

Related Questions