DEV Community

Cover image for Context leaking in EmberJS tests
Michal Bryxí
Michal Bryxí

Posted on

Context leaking in EmberJS tests

(Unit) tests should be FIRST: Fast, Isolated, Repeatable, Self-Verifying, and Timely. The I part is important for this case, specifically:

No order-of-run dependency. They should pass or fail the same way in suite or when run individually.

Usual case that makes I break is "test pollution".

The problem

Imagine following test code:

import { module, test } from 'qunit';
import { setupRenderingTest } from 'sandbox/tests/helpers';

let globalScopedProperty = 'foo';

module('Integration | Component | foo', function (hooks) {
  setupRenderingTest(hooks);

  let moduleScopedProperty = 'foo';

  hooks.beforeEach(function () {
    this.beforeEachScopedProperty = 'foo';
  });

  test('test A', async function (assert) {
    globalScopedProperty = 'bar';
    moduleScopedProperty = 'bar';
    this.beforeEachScopedProperty = 'bar';
    let testScopedProperty = 'bar';

    assert.ok(true); // just to have one assert
  });

  test('test B', async function (assert) {
    let testScopedProperty;

    assert.strictEqual(globalScopedProperty, 'foo', 'global scope');
    assert.strictEqual(moduleScopedProperty, 'foo', 'module scope');
    assert.strictEqual(testScopedProperty, undefined, 'test scope');
    assert.strictEqual(this.beforeEachScopedProperty, 'foo', 'before each scope');
  });
});
Enter fullscreen mode Exit fullscreen mode
  • Now if we happen to run test B first, and then test A, then everything will be green.
  • But if we will run test A first and then test B we will get two of the tests failing.

Asserts for "global scope" and "module scope" failed

This is not great. And this can and will come to bite you later on when code gets extended / refactored and unintended variable mutations will happen. It does not even have to be direct mutation of the property itself, but write operation to some nested element of an object.

Conclusion

  • Tests can and will run in random order. Maybe not now, maybe not next time you execute the tests, but eventually they will.
  • EmberJS test suite will make sure that beforeEachScopedProperty wil get re-set before each test.
  • By the way JavaScript works testScopedProperty will exist only within scope of your test and will get re-set before each test even if multiple tests happen to declare variable with the same name.
  • If you want to define a property that is used in every test, then use beforeEach hook and store it in beforeEachScopedProperty.
  • Do not try to make values from one test leak into other test. Always assume clean state.

Image created with Midjourney via prompt: Tomster EmberJS macot; Leaking context --aspect 16:9

Top comments (0)