Симуляция ответов сервера

Тестирование кода, который взаимодействует с сервером, является важной частью процесса разработки. В реальных условиях ответы от сервера могут быть медленными или нестабильными, что усложняет процесс тестирования. Чтобы избежать таких проблем, можно использовать симуляцию серверных ответов. В Jasmine для этой цели обычно применяют шпионов и моки, позволяя эмулировать поведение HTTP-запросов без необходимости реально отправлять их на сервер.

Использование spyOn для перехвата запросов

Метод spyOn в Jasmine позволяет шпионить за функциями, перехватывая их вызовы и предоставляя возможность заменять их реализации. Это полезно при тестировании кода, который выполняет HTTP-запросы.

Для начала рассмотрим базовый пример, где нужно симулировать ответ сервера, чтобы проверить правильность обработки данных.

describe('Симуляция ответов сервера с использованием spyOn', function() {
  it('Должен корректно обработать успешный ответ от сервера', function() {
    const httpService = {
      getData: function(url) {
        return fetch(url).then(response => response.json());
      }
    };

    const mockResponse = { success: true, data: 'Test Data' };
    spyOn(window, 'fetch').and.returnValue(Promise.resolve({
      json: () => Promise.resolve(mockResponse)
    }));

    httpService.getData('/test-url').then(response => {
      expect(response).toEqual(mockResponse);
    });
  });
});

В этом примере метод fetch был перехвачен с помощью spyOn, и вместо реального выполнения HTTP-запроса возвращается промис с заранее подготовленным ответом. Это позволяет тестировать логику обработки данных без необходимости выполнять реальные запросы.

Моки для имитации серверных ответов

Моки — это специальные объекты, которые имитируют поведение настоящих объектов, но предоставляют фиксированное поведение для тестов. В случае с симуляцией ответов сервера моки могут быть полезны для более сложных сценариев, когда нужно контролировать не только успешные, но и ошибочные ответы.

describe('Мок серверного ответа с ошибкой', function() {
  it('Должен корректно обработать ошибку сервера', function() {
    const httpService = {
      getData: function(url) {
        return fetch(url).then(response => response.json());
      }
    };

    const mockErrorResponse = { error: 'Server Error' };
    spyOn(window, 'fetch').and.returnValue(Promise.reject(mockErrorResponse));

    httpService.getData('/test-url').catch(error => {
      expect(error).toEqual(mockErrorResponse);
    });
  });
});

Здесь с помощью spyOn на fetch мы симулируем отклонённый промис с ошибкой, что позволяет протестировать обработку ошибок в коде, который зависит от внешнего сервера.

Использование библиотеки jasmine-ajax

В некоторых случаях, когда необходимо более детально контролировать поведение HTTP-запросов, можно использовать дополнительные библиотеки, такие как jasmine-ajax. Эта библиотека предоставляет удобные методы для работы с AJAX-запросами, включая их имитацию.

Для использования jasmine-ajax необходимо сначала настроить библиотеку:

beforeEach(function() {
  jasmine.Ajax.install();
});

afterEach(function() {
  jasmine.Ajax.uninstall();
});

Затем можно использовать методы jasmine.Ajax.requests для контроля запросов. Например, чтобы симулировать ответ на AJAX-запрос:

describe('Симуляция AJAX запросов с использованием jasmine-ajax', function() {
  it('Должен обработать успешный ответ от сервера', function() {
    const httpService = {
      getData: function(url) {
        return $.ajax({ url: url, method: 'GET' });
      }
    };

    httpService.getData('/test-url');

    const request = jasmine.Ajax.requests.mostRecent();
    request.respondWith({
      status: 200,
      responseText: '{"success": true, "data": "Test Data"}'
    });

    request.done(function(response) {
      expect(response.success).toBe(true);
      expect(response.data).toBe('Test Data');
    });
  });
});

В этом примере мы не только контролируем ответ сервера, но и задаём статус и текст ответа через respondWith, что даёт полный контроль над тестируемыми запросами.

Обработка задержек с помощью мока

В реальных условиях запросы к серверу могут занимать разное время. Для симуляции таких задержек можно использовать таймеры или мокировать время ответа сервера.

describe('Симуляция задержки при получении данных', function() {
  it('Должен обработать задержку ответа сервера', function(done) {
    const httpService = {
      getData: function(url) {
        return new Promise(resolve => {
          setTimeout(() => resolve({ success: true, data: 'Delayed Data' }), 1000);
        });
      }
    };

    const mockResponse = { success: true, data: 'Delayed Data' };
    
    spyOn(httpService, 'getData').and.callFake(function() {
      return new Promise(resolve => {
        setTimeout(() => resolve(mockResponse), 1000);
      });
    });

    httpService.getData('/test-url').then(response => {
      expect(response).toEqual(mockResponse);
      done();
    });
  });
});

В данном примере используется setTimeout для имитации задержки. Важно помнить, что в Jasmine для асинхронных тестов нужно использовать функцию done, чтобы указать завершение теста.

Проверка запросов с помощью jasmine-ajax

Помимо симуляции ответов, можно проверить, какие именно запросы были отправлены и как они были сформированы. Это особенно полезно, когда нужно удостовериться, что запросы отправляются с правильными параметрами и заголовками.

describe('Проверка запросов с использованием jasmine-ajax', function() {
  it('Должен отправить запрос с правильными параметрами', function() {
    const httpService = {
      getData: function(url, params) {
        return $.ajax({ url: url, method: 'GET', data: params });
      }
    };

    httpService.getData('/test-url', { userId: 1 });

    const request = jasmine.Ajax.requests.mostRecent();
    expect(request.url).toBe('/test-url');
    expect(request.params()).toEqual({ userId: '1' });
  });
});

Здесь используется jasmine.Ajax.requests.mostRecent(), чтобы получить последний отправленный запрос и проверить его параметры.

Заключение

Симуляция ответов сервера с использованием Jasmine позволяет легко тестировать код, который зависит от внешних API, не выполняя реальных HTTP-запросов. Использование шпионов, моков и дополнительных библиотек, таких как jasmine-ajax, предоставляет мощные инструменты для эмуляции серверного взаимодействия, контроля ответов и проверки правильности работы асинхронных операций.