Использование this в тестах

В Jasmine объект this играет особую роль и отличается от стандартного поведения this в JavaScript. В тестах и хуках (beforeEach, afterEach) он используется как контекст для хранения данных, общих для набора тестов или отдельных спеков. Понимание работы this критично для организации чистого и изолированного тестирования.


Контекст this в describe и it

Каждый блок describe в Jasmine создаёт собственный контекст this, который наследуется вложенными блоками describe. Внутри it this ссылается на объект контекста теста, созданного на уровне родительского describe. Это позволяет:

  • Хранить значения, доступные всем спекам внутри блока describe.
  • Избегать глобальных переменных.
  • Делить состояние между хук-функциями и спеками.

Пример:

describe('Работа с контекстом this', function() {
  beforeEach(function() {
    this.counter = 0;
  });

  it('увеличивает счетчик', function() {
    this.counter += 1;
    expect(this.counter).toBe(1);
  });

  it('сбрасывает счетчик для каждого теста', function() {
    expect(this.counter).toBe(0);
  });
});

В этом примере видно, что this.counter не сохраняет значение между разными тестами — каждый it получает новый контекст.


Ограничения использования this

  1. Стрелочные функции нельзя использовать с this Стрелочные функции захватывают this из лексического окружения, а не создают собственный контекст Jasmine. Поэтому:
describe('Некорректное использование стрелочных функций', () => {
  beforeEach(() => {
    this.value = 42; // this не относится к Jasmine
  });

  it('тест не будет работать', () => {
    expect(this.value).toBe(42); // undefined
  });
});
  1. this создаётся для каждого describe Контекст не глобальный — вложенные describe получают копию контекста родителя, что важно учитывать при организации сложных иерархий тестов.

Использование this в хуках

  • beforeEach и afterEach Контекст this позволяет подготовить данные перед каждым тестом и очищать их после.

  • beforeAll и afterAll Контекст this доступен, но все тесты используют один и тот же объект, поэтому изменение данных в одном тесте может повлиять на другие.

Пример:

describe('Тестирование с beforeAll и beforeEach', function() {
  beforeAll(function() {
    this.sharedValue = 100;
  });

  beforeEach(function() {
    this.tempValue = this.sharedValue + 1;
  });

  it('использует значения', function() {
    expect(this.tempValue).toBe(101);
  });

  it('tempValue сбрасывается для каждого теста', function() {
    expect(this.tempValue).toBe(101);
  });
});

Рекомендации по работе с this

  1. Использовать this только в обычных функциях, не в стрелочных.
  2. Хранить только данные тестового состояния, не методы. Методы лучше выносить в отдельные вспомогательные функции.
  3. Для сложных структур состояния можно использовать вложенные объекты:
beforeEach(function() {
  this.state = {
    user: { name: 'Alice' },
    items: []
  };
});
  1. Не смешивать this и глобальные переменные для одних и тех же целей, чтобы избежать конфликтов и непредсказуемого поведения.
  2. Использовать beforeEach для инициализации состояния, чтобы каждый тест был независимым и изолированным.

Особенности наследования контекста

Вложенные describe создают отдельный объект this, который не мутирует родительский контекст, но может читать свойства родителя:

describe('Верхний describe', function() {
  beforeEach(function() {
    this.value = 10;
  });

  describe('Вложенный describe', function() {
    it('видит значение родителя', function() {
      expect(this.value).toBe(10); // читаем, но можно изменять локально
      this.value += 5;
      expect(this.value).toBe(15);
    });

    it('сбрасывает значение после предыдущего теста', function() {
      expect(this.value).toBe(10);
    });
  });
});

Таким образом, каждый тест остаётся изолированным, а родительский контекст обеспечивает общие данные.


Примеры типичных ошибок

  • Использование стрелочной функции в beforeEach или it:
it('неправильное использование this', () => {
  this.value = 5; // undefined
});
  • Смешивание состояния между тестами без beforeEach:
describe('Состояние между тестами', function() {
  this.counter = 0;

  it('увеличивает', function() {
    this.counter += 1;
    expect(this.counter).toBe(1);
  });

  it('ожидается сброс', function() {
    expect(this.counter).toBe(0); // будет 1 — ошибка
  });
});

Правильный вариант — инициализация через beforeEach.


Использование this в Jasmine — это удобный инструмент для изоляции состояния тестов, управления общими данными и обеспечения чистоты тестового окружения. Основное правило: всегда использовать обычные функции и beforeEach для инициализации, а вложенные describe использовать для логической группировки тестов и наследования контекста.