Отделение покрытия ноль процентов в шутку - PullRequest
0 голосов
/ 05 ноября 2018

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

request.js

import axios from 'axios';

export default async (request, httpService = axios) => {
  const {
    method, url, data, headers,
  } = request;
  return httpService.request({
    method,
    url,
    headers: Object.assign({}, headers),
    data,
  });
};

reqeust.test.js

describe('requestServie', () => {
  it('should have a valid request object', async () => {
    const requestObj = {
      method: 'POST',
      url: 'http://mock.url',
      data: {},
    };

    const mockRequest = jest.fn(() => Promise.resolve({}));

    const httpService = {
      request: mockRequest,
    };

    await request(requestObj, httpService);
    expect(mockRequest).toHaveBeenCalledWith({
      method: requestObj.method,
      url: requestObj.url,
      headers: {},
      data: requestObj.data,
    });
  });

  it('should return a valid response (empty)', async () => {
    const response = {
      data: {
      },
      status: 200,
      statusText: 'OK',
      headers: {},
      config: {},
      request: {},
    };

    const mockRequest = jest.fn(() => Promise.resolve(response));

    const httpService = {
      request: mockRequest,
    };

    const res = await request({ url: 'http://mock.url' }, httpService);

    expect(res).not.toBe(null);
    expect(res).toMatchObject(
      {
        status: response.status,
      },
    );
  });
});

Редактировать

rquest.js

export default async (request, httpService = axios) => {
  const {
    method, url, data, headers,
  } = request;
  return httpService.request({
    method,
    url,
    headers: Object.assign({}, headers),
    data,
  }).then(successResponse, (error) => {
    throwHttpError(error);
  });
};

request.test.js

import HttpError from 'standard-http-error';
import axios from 'axios';
import request, { successResponse, throwHttpError } from './requestService';

describe('requestService', () => {

  jest.mock('axios', () => ({
    request: jest.fn(() => Promise.resolve({})),
  }));

  describe('successResponse', () => {
    const mockRes = {
      status: 9001,
      data: {
        stuff: 'stuff',
      },
    };
    it('should returns an object with only status and data properties', () => {
      const responseKeys = Object.keys(successResponse(mockRes));
      expect(responseKeys).toMatchObject(['status', 'data']);
      expect(responseKeys.length).toBe(2);
    });

    it('should map the status of the reponse to the status property', () => {
      expect(successResponse(mockRes).status)
        .toBe(mockRes.status);
    });

    it('should map the data of the reponse to the data property', () => {
      expect(successResponse(mockRes).data)
        .toMatchObject(mockRes.data);
    });

    it('should have a valid request object', async () => {
      const requestObj = {
        method: 'POST',
        url: 'http://mock.url',
        data: {},
        headers: {},
      };

      const mockRequest = jest.fn(() => Promise.resolve({}));

      const httpService = {
        request: mockRequest,
      };

      await request(requestObj, httpService);
      expect(mockRequest).toHaveBeenCalledWith({
        method: requestObj.method,
        url: requestObj.url,
        headers: {},
        data: requestObj.data,
      });
    });
  });

  describe('httpThrowError', () => {
    const mockErr = {
      response: {
        status: 9001,
        statusText: 'error message goes here',
      },
    };

    it('should map the status of the reponse to the error.status property', () => {
      try {
        throwHttpError(mockErr);
      } catch (e) {
        expect(e).not.toBe(null);
        expect(e.status).toBe(mockErr.response.status);
        expect(e.message).toBe(mockErr.response.statusText);
      }
    });

    it('should map the data of the reponse to the error.data property', () => {
      const mockErrWithData = Object.assign({}, mockErr);
      mockErrWithData.response.data = {};
      try {
        throwHttpError(mockErrWithData);
      } catch (e) {
        expect(e).not.toBe(null);
        expect(e.data).toBe(mockErrWithData.response.data);
      }
    });
  });

  describe('request', () => {
    const testCases = [
      ['should return error response on server error', 500],
      ['should return error response on bad request', 400],
      ['should return error response on unauthorised', 401],
    ];

    testCases.forEach(([testName, errorStatus]) => {
      it(testName, async () => {
        const errorResponse = {
          response: {
            status: errorStatus,
          },
        };
        const mockRequest = jest.fn(() => Promise.reject(errorResponse));

        const httpService = {
          request: mockRequest,
        };

        try {
          await request({ url: 'http://mock.url' }, httpService);
          throw new Error('Expected an exception, but none was thrown');
        } catch (err) {
          expect(err).not.toBe(null);
          expect(err).toMatchObject(
            new HttpError(errorResponse.response.status,
              errorResponse.response.statusText),
          );
        }
      });
    });

    it('should return an valid response (empty)', async () => {
      const response = {
        data: {
          meta: {},
          results: [],
        },
        status: 200,
        statusText: 'OK',
        headers: {},
        config: {},
        request: {},
      };

      const mockRequest = jest.fn(() => Promise.resolve(response));

      const httpService = {
        request: mockRequest,
      };

      const res = await request({ url: 'http://mock.url' }, httpService);

      expect(res).not.toBe(null);
      expect(res).toMatchObject(
        {
          status: response.status,
          data: response.data,
        },
      );
    });

    it('should use axios by default', async () => {
      const req = { url: 'http://mock.url', method: 'get' };
      await request(req);
      expect(axios.request).toHaveBeenCalled();
    });
  });
});

Error

enter image description here

enter image description here

enter image description here

Обновлено 15 ноября / 18

"шутка": "^ 23.6.0",

import HttpError from 'standard-http-error';
import axios from 'axios';
import request, { successResponse, throwHttpError } from './requestService';

jest.mock('axios', () => ({
  request: jest.fn(),
}));

Error

enter image description here

1 Ответ

0 голосов
/ 06 ноября 2018

Чтобы увидеть, что не покрыто, вы можете перейти к coverage/Iconv-report и открыть index.html. Они создаются после запуска jest с параметром --coverage .

Похоже, что непокрытая ветка: httpService = axios. Поэтому вам нужно проверить, используется ли значение по умолчанию axios.

Чтобы покрыть это, вы можете запустить запрос без аргумента httpService - вы можете макет axios глобально для этого, то есть:

import axios from 'axios';

// note that mock goes before any describe block

jest.mock('axios', () => {
  return {
    request: jest.fn(() => Promise.resolve({})),
  }
});

describe('requestService', () => {

  // ... your other tests

  it('should use axios by default', async () => {
    const opts = { url: 'http://mock.url', method: 'get' };
    const res = await request(opts);
    expect(axios.request).toHaveBeenCalled();
  });
});

Обратите внимание, что jest.mock имеет некоторые ошибки при работе внутри спецификации .

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