为什么这个模拟api不能按预期工作?

时间:2016-10-14 13:04:24

标签: javascript reactjs ecmascript-6 jestjs fetch-api

我试图测试这个简单的api模块:

import fetch from 'isomorphic-fetch';

export const getJson = (endpoint: string) => {
  const options = { credentials: 'include', method: 'GET' };

  return fetch(endpoint, options)
    .then(response => response.json()
      .then(json => {
        if (response.ok) return json;
        return Promise.reject(json.errors);
      })
    )
    .catch(error => {
      if (error.constructor === Array) return error;
      return [error.message];
    });
};

通过这个测试,我在嘲笑fetch:

import { getJson } from '../api';

const mockResponse = (status, statusText, response) => {
  return new window.Response(response, {
    status: status,
    statusText: statusText,
    headers: {
      'Content-type': 'application/json'
    }
  });
};

describe('api middleware', () => {
  describe('getJson', () => {
    it('should return the response on success', () => {
      const expected = { data: ['data'], meta: {} };
      const body = JSON.stringify(expected);

      window.fetch = jest.fn().mockImplementation(() =>
        Promise.resolve(mockResponse(200, null, body)));

      return getJson('http://endpoint').then(actual => expect(actual).toEqual(expected));
    });
  });
});

但测试失败了:

Expected value to equal:
  {"data": ["data"], "meta": {}}
Received:
  ["Unexpected end of JSON input"]

Difference:

Comparing two different types of values:
  Expected: object
  Received: array

我还没弄清楚为什么这不起作用。为什么我收到"意外结束JSON输入"错误?如何在测试中成功模拟本地获取?在this medium post中,它基本上以相同的方式完成..

2 个答案:

答案 0 :(得分:0)

显然测试仍在使用全局获取库,而不是我的修补版本。解决方案是:

  1. 删除'isomorphic-fetch'模拟(在项目根目录的__mocks__中)。
  2. 使用import 'isomorphic-fetch;
  3. 在项目的根目录中导入“isomorphic-fetch”一次
  4. 删除api模块顶部的'isomorphic-fetch'导入(因为它已经在入口点导入了
  5. 将测试更新为:
  6. 试验:

    // to make the Response constructor available
    import 'isomorphic-fetch';
    import { getJson } from '../api';
    
    describe('api middleware', () => {
      describe('getJson', () => {
        beforeEach(() => {
          window.fetch = jest.genMockFunction();
        });
    
        it('should return the response on success', () => {
          const expected = { data: ['data'], meta: {} };
          const body = JSON.stringify(expected);
          const init = { status: 200, statusText: 'OK' };
    
          window.fetch.mockReturnValueOnce(Promise.resolve(new Response(body, init)));
    
          return getJson('http://endpoint').then(actual => expect(actual).toEqual(expected));
        });
      });
    });
    

答案 1 :(得分:-1)

很可能是因为您的fetch函数不使用全局(窗口)getJson

我建议的方法是使用Dependency Injection (DI); make fetch检索&#34; http请求&#34;库/函数(在您的情况下为var webdriver = require('selenium-webdriver'), By = webdriver.By, until = webdriver.until; for (let i = 0; i < 3; i++) { var flow = new webdriver.promise.ControlFlow() .on('uncaughtException', function(e) { console.log('uncaughtException in flow %d: %s', i, e); }); var driver = new webdriver.Builder().forBrowser('chrome').setControlFlow(flow).build(); driver.get('http://www.google.com'); driver.findElement(By.name('q')).sendKeys('webdriver'); driver.findElement(By.name('btnG')).click(); driver.wait(until.titleIs('webdriver - Google Search'), 1000); driver.quit(); } )并在测试中创建一个注入的模拟函数。 mock函数将返回您想要的数据作为测试的一部分。