fetch-mock 模拟所有请求

fetch-mock mocking all requests

我正在使用 fetch-mock 来模拟对服务器的一些请求。这是发出所有请求的地方:

import fetchMock from 'fetch-mock'
import initialState from 'src/initial-state'

if (process.env.NODE_ENV === 'development') {
  fetchMock.post('/some/endpoint', initialState.entities.multichannelEngagement)
}

但是不仅这个端点被模拟了,所有使用同构获取的请求都被模拟了

import 'isomorphic-fetch'
export function makeRequest(endpoint, config = {}) {
  return window.fetch(endpoint, config)
  .then(response => {
    return response.json()
  .then(json => ({ json, response }))
  .catch(() => ({ response }))
})
.then(({ json, response }) => {
  if (!response.ok) {
    throw json ? json : new Error(response.statusText)
  } else {
    return json
  }
})
.catch((e) => {
  return Promise.reject(e)
})

}

我的webpack.config.js如下:

import path from 'path'
import dotenv from 'dotenv'
import webpack from 'webpack'
import info from './package.json'

const resolvePath = p => path.join(__dirname, p)

const __DEV__ = process.env.NODE_ENV !== 'production'

const { parsed: env } = dotenv.load()
env.NODE_ENV = process.env.NODE_ENV
Object.keys(env).forEach(k => env[k] = JSON.stringify(env[k]))

const config = {
  name: info.name,

  entry: {
    app: 'src/index',
    vendor: Object.keys(info.dependencies)
  },

  output: {
    path: __DEV__ ? resolvePath('public') : resolvePath('../analytics-server/server/public'),
    filename: '/js/[name].js',
    publicPath: '/',
    debug: __DEV__,
    pathinfo: __DEV__
  },

  module: {
    preLoaders: [{
      // NOTE: Run linter before transpiling
      test: /\.js$/,
      loader: 'eslint-loader',
      exclude: /node_modules/
    }],
    loaders: [{
      test: /\.js$/,
      loader: 'babel',
      exclude: /node_modules/
    }, {
      // TODO: Remove after upgrading to webpack 2
      test: /\.json$/,
      loader: 'json'
    }]
  },

  resolve: {
    alias: {
      src: resolvePath('src'),
      core: resolvePath('src/core'),
      components: resolvePath('src/components'),
      modules: resolvePath('src/modules'),
      services: resolvePath('src/services'),
      resources: resolvePath('src/resources'),
      locales: resolvePath('src/locales')
    },
    // NOTE: Empty string to properly resolve when providing extension
    // TODO: Remove after upgrading to webpack 2
    extensions: ['', '.js']
  },

  plugins: [
    // NOTE: `NoErrorsPlugin` causes eslint warnings to stop the build   process
    // new webpack.NoErrorsPlugin(),
    new webpack.optimize.CommonsChunkPlugin('commons', '/js/commons.js'),
    new webpack.DefinePlugin({ process: { env } })
// new webpack.NormalModuleReplacementPlugin( /^fetch-mock$/, path.resolve( __dirname, 'node_modules', 'fetch-mock/src/client.js' ) )
  ],

  eslint: {
    configFile: resolvePath('.eslintrc')
  }
}

if (__DEV__) {
  config.devtool = 'source-map'

  config.devServer = {
    contentBase: 'public',
    // NOTE: Options `inline` and `hot` shall be passed as CLI arguments
    // inline: true,
    // hot: true,
    historyApiFallback: true
  }
} else {
  config.plugins.push(...[
    new webpack.optimize.DedupePlugin(),
    new webpack.optimize.OccurenceOrderPlugin(),
    new webpack.optimize.UglifyJsPlugin({
      compress: true,
      acorn: true
    })
  ])
}

export default config

我在 运行 应用程序时遇到的错误是 "fetch-mock.js:93 Uncaught Error: No fallback response defined for GET to http://localhost:3000/api/session" 这是在应用程序中发出的第一个请求。

不知道为什么 fetch-mock 会模拟所有请求。在 chrome 控制台上进行评估时,makeRequest 函数上的 fetch 值是 fetch-mock 函数,但据我所知这是正确的。

顺便说一句,我不在测试环境,我在开发,因为我需要模拟我的后端,因为它还没有完成。

知道为什么会这样吗?

提前致谢

问题是因为fetch-mock的主要目的是帮助测试。在测试环境中,如果您对正在调度的任何 non-mocked 个调用获得异常,则更好。

然而,您可以添加一个 catch 委托给原始 fetch 的处理程序,因此任何 non-mocked 请求都会传递给真正的提取。类似于以下内容:

/* FAKE FETCH ME */
  fetchMock.get('/session', function getSession(url, opts) {
    const jwt = extractToken(opts)
    if (!jwt || jwt !== fakeToken) {
      return delay({
        status: 401,
        body: JSON.stringify({
          details: 'Unauthorized'
        })
      })
    }
    return delay({
      status: 200,
      body: JSON.stringify({
        success: true,
        data: fakeUserDetails
      })
    })
  })
  .catch(unmatchedUrl => {
    // fallover call original fetch, because fetch-mock treats
    // any unmatched call as an error - its target is testing
    return realFetch(unmatchedUrl)
  })

该库过去有一个选项,但在 V5 中被删除了。请参阅此处的文档:

In previous versions fetch-mock had a greed property, set to

  • good - unmatched calls respond with a 200
  • bad - unmatched calls error
  • none - allow unmatched calls to use native fetch and the network

This has now been replaced by a .catch() method which accepts the same types of response as a normal call to .mock(matcher, response). It can also take an arbitrary function to completely customise behaviour of unmatched calls. It is chainable and can be called before or after other calls to .mock(). The api to check for unmatched calls remains unchanged.

https://github.com/wheresrhys/fetch-mock/blob/master/V4_V5_UPGRADE_NOTES.md#handling-unmatched-calls-greed

从 fetch-mock v.6.5 开始有一个名为 fallbackToNetwork 的新配置 属性 允许您控制 fetch-mock 处理未处理(未匹配)呼叫的方式

http://www.wheresrhys.co.uk/fetch-mock/#usageconfiguration