mocha: 🐛 Bug: Contexts not properly reset between tests within the same level

Hey,

I wouldn’t be surprised if related to my years old bug report and gripe: https://github.com/mochajs/mocha/issues/1195

var assert = require("assert")

describe("Parent", function() {
  beforeEach(function() { this.value = 42 })

  it("must pass 1", function() { assert.equal(this.value, 42) })
  it("must pass 2", function() { assert.equal(this.value, 42) })

  describe("Child", function() {
    beforeEach(function() {
      assert.equal(this.value, 42)
      this.value = 13
    })

    it("must pass 1", function() { assert.equal(this.value, 13) })
    it("must pass 2", function() { assert.equal(this.value, 13) })
  })
})

Fails with:

  1) Parent Child "before each" hook for "must pass 2":

      AssertionError: 13 == 42
      + expected - actual

      -13
      +42

      at Context.<anonymous> (test/index_test.js:11:14)

About this issue

  • Original URL
  • State: open
  • Created 9 years ago
  • Reactions: 3
  • Comments: 46 (20 by maintainers)

Most upvoted comments

Thanks for the quick response.

But it’s up to you to clean up state in an afterEach/beforeEach hook.

That doesn’t make sense. Contexts need to be reset automatically. That’s their whole point: to save from a mind numbing number of afterEach(function() { delete this.a; delete this.b }). Don’t you agree the current behavior is just weird: beforeEaches clearly run before each test, but their assignments don’t show up, as is visible in my first post?

I agree that sharing state between tests is a bad idea 😃 But it’s up to you to clean up state in an afterEach/beforeEach hook. I see these two suites as equal:

var assert = require('assert');

describe('Suite1', function() {
  it('test1', function() {
    this.value = 'foo';
    assert.equal(this.value, 'foo');
  });

  it('test2', function() {
    assert.notEqual(this.value, 'foo');
  });
});

describe('Suite2', function() {
  var value;

  it('test1', function() {
    value = 'foo';
    assert.equal(value, 'foo');
  });

  it('test2', function() {
    assert.notEqual(value, 'foo');
  });
});
  Suite1
    ✓ test1
    1) test2

  Suite2
    ✓ test1
    2) test2

There’s nothing too fancy going on here.

Even if they were left there, assignments in beforeEach must take precedence. 😉

Not sure what you’re talking about

I would expect to not have this.value set in “test2”. Sharing properties between tests such a way is despicable. Even if they were left there, assignments in beforeEach must take precedence. 😉

I’m sure still am interested in this.

@moll I disagree. I always write all of my tests using function scopes if I need to make a value available. Indeed, this is pretty foolproof:

describe('something', () => {
  let foo;
  beforeEach(() => {
    foo = {};
  });

  it('should do something with foo...', () => {
    ///
  });
});

I’ve never understood the necessity of using this to make a value available. It leads to problems, which is why we have bugs like this one.

Hello,

I haven’t read the whole thing but I found a case when using https://github.com/dareid/chakram, test isolation fails. If, within a describe, I have a test failure, all following tests are failing as well.

I use a beforeEach to set up some chakram configuration like HTTP headers or so but each test is doing its own HTTP request and I don’t understand how one failure could cause following ones to fail as well although they don’t rely on it.

Could you advise please? For now, the only solution I found to efficiently help debug is to use the the --bail option so when one is failing, we focus on the first failure.

Thanks!

I would strongly urge users to not use this for storing values, ever.