Search code examples
javascriptunit-testingmocha.js

Mocha and the this context


So I have this code with nested describe:

describe('main describe', function() {
    afterEach(function() {
      //this.prop === undefined
    });

    describe('sub', function() {
        it('should do something', function() {
            this.prop = 'test';
        });
    });
});

I don't know why this.prop in the main afterEach is undefined because the following code without nested describe works as expected:

describe('main describe', function() {
    afterEach(function() {
      //this.prop === 'test'
    });

    it('should do something', function() {
        this.prop = 'test';
    });
});

Why does the first code not work as I though it would where this.prop should equal 'test' and not undefined?

Is the this keyword tied to only the describe function it is directly contained it?


Solution

  • Yep, each describe gets a new Context object. (All the classes I mention can be found in Mocha's source code.) You could get what you are trying to do with:

    describe('main describe', function() {
        afterEach(function() {
            console.log(this.prop);
        });
    
        describe('sub', function() {
            it('should do something', function() {
                this.test.parent.ctx.prop = 'test';
            });
        });
    });
    

    The line this.test.parent.ctx.prop is the key. this is the Context associated with the it call. this.test is the Test object associated with the it call. this.test.parent is the Suite object associated with the describe call that immediately contains the it call. this.test.parent.ctx is the context in effect where the describe call appears, which happens to be the same context as this in the afterEach call.

    I would actually recommend not traversing Mocha's internal structures and instead doing something like:

    describe('main describe', function() {
        var prop;
        afterEach(function() {
            console.log(prop);
        });
    
        describe('sub', function() {
            it('should do something', function() {
                prop = 'test';
            });
        });
    });