从获取请求返回的 JSON 在测试和开发中不同

Returned JSON from fetch requests differs in test and dev

我希望我的问题标题足够易于理解。我真的想不出更好的措辞方式,字符数限制让我崩溃了。

我遇到的问题发生在我正在处理的项目中,该项目使用 React、Redux 和 react-router-redux 和 redux-auth-wrapper 等软件包。

为了进行测试,我将 Karma 测试运行器与 Enzyme、Sinon 和 Chai 一起使用。在测试中,我使用 fetchMock 来模拟对我正在使用的 API 的任何请求。我使用 Webpack 捆绑所有内容。

我面临的问题是我编写的代码(相当严格地修改了 this 入门模板)有效,但我为他们编写的测试没有产生正确的结果。有点奇怪的是当我发送一个动作来从我们的身份验证中获取令牌时 API.

我正在调度的 Redux 操作如下:

export function fetchToken(data) {
  return function(dispatch) {
    dispatch(requestTokenCreate(data))

    // Let's fetch this user a token, shall we?
    var headers = new Headers()
    headers.append("Content-Type", "application/json")
    headers.append("Accept", "application/json")

    let requestParams = {
      method: 'POST',
      headers: headers,
      mode: 'cors',
      cache: 'default',
      body: JSON.stringify({
        subdomain: data.subdomain,
        login: data.username,
        password: data.password
      })
    }
    data = {
      subdomain: data.subdomain,
      username: data.username
    }
    var serverUrl = (__DEV__ || __TEST__) ? "http://subdomain.easyposonline.dev:3000/api/v1" : "https://subdomain.easyposonline.nl/api/v1"
    serverUrl = serverUrl.replace("subdomain", data.subdomain)
    return fetch(serverUrl + "/auth_tokens/create", requestParams)
      .then(response => response.json())
      .then(json => {
        return dispatch(receiveTokenCreate(json, data))
      }
    )
  }
}

与我的问题相关的部分是:

return fetch(serverUrl + "/auth_tokens/create", requestParams)
  .then(response => response.json())
  .then(json => {
      return dispatch(receiveTokenCreate(json, data))
  }
)

当我在我的开发代码中调度这个动作时,它工作得很好!此 returns 以下响应:

{success: true, token: "a3PC6y6nx1f63o2b13YWz7LYUHdidYui"}

不过,当从相关测试中分派操作时,我收到以下响应:

{type: 'RECEIVE_USER_TOKEN_CREATE', json: Object{success: true, token: 'qicXyn6BhYhyoBuA_SFoZtTDN'}, payload: Object{subdomain: 'test-teun', username: 'teun@easypos.nl', token: 'qicXyn6BhYhyoBuA_SFoZtTDN'}}

因此,代码 returns 没有返回正确的响应,而是一个完整的 Redux 操作。这导致我的测试失败,因为我最终在我正在测试的代码中进行了一些递归:

{type: 'RECEIVE_USER_TOKEN_CREATE', response: Object{type: 'RECEIVE_USER_TOKEN_CREATE', json: Object{success: ..., token: ...}, payload: Object{subdomain: ..., username: ..., token: ...}}, payload: Object{subdomain: 'test-teun', username: 'teun@easypos.nl'}}

我在这里不知所措。可能我忽略了一些非常简单的事情,但现在已经看了几个小时并且开始失去理智!

我写的测试文件如下,可能我设置的测试方式不对:

import configureMockStore from 'redux-mock-store'
import thunk from 'redux-thunk'
// import nock from 'nock'
import 'isomorphic-fetch'
import fetchMock from 'fetch-mock'

import SignInView from 'routes/SignIn'
import * as constants from 'constants'
import { fetchToken, destroyToken } from 'actions/user'
import _ from 'underscore'

describe('(Route) SignIn', () => {
  let _route = SignInView({})

  // Auth token request
  const authTokenCreateSuccessfulRequest = {
    subdomain: 'test-teun',
    username: 'teun@easypos.nl',
    password: 'psv4teun'
  }
  const authTokenCreateFailedRequest = {
    subdomain: 'test-teun',
    username: 'teun@easypos.nl',
    password: 'teun4psv'
  }
  const authTokenCreateSuccessfulResponse = {
    type: constants.RECEIVE_USER_TOKEN_CREATE,
    json: {
      success: true,
      token: 'qicXyn6BhYhyoBuA_SFoZtTDN'
    },
    payload: {
      subdomain: 'test-teun',
      username: 'teun@easypos.nl',
      token: 'qicXyn6BhYhyoBuA_SFoZtTDN'
    }
  }
  const authTokenCreateFailedResponse = {
    type: constants.RECEIVE_USER_TOKEN_CREATE,
    json: {
      success: false,
      reason: "Ongeldige gebruikersnaam of wachtwoord!"
    },
    payload: {
      subdomain: 'test-teun',
      username: 'teun@easypos.nl'
    }
  }

  beforeEach(() => {
    fetchMock.mock('http://test-teun.easyposonline.dev:3000/api/v1/auth_tokens/create', authTokenCreateSuccessfulResponse)
  })

  afterEach(() => {
    fetchMock.restore()
  })

  it('Should return a route configuration object', () => {
    expect(typeof _route).to.equal('object')
  })

  it('Should define a route component', () => {
    expect(_route.path).to.equal('sign_in')
  })

  const middlewares = [ thunk ]
  const mockStore = configureMockStore(middlewares)

  it('Should trigger RECEIVE_USER_TOKEN_CREATE action containing a token on a successful login attempt', () => {
    //fetchMock.mock('http://test-teun.easyposonline.dev:3000/api/v1/auth_tokens/create', authTokenCreateSuccessfulResponse)
    const expectedActions = [
      {
        type: constants.REQUEST_USER_TOKEN_CREATE,
        payload: authTokenCreateSuccessfulRequest
      },
      authTokenCreateSuccessfulResponse
    ]
    const store = mockStore({ user: { isFetching: false } })

    return store.dispatch(fetchToken(authTokenCreateSuccessfulRequest))
      .then((data) => {
        console.log(store.getActions()[1])
        // console.log(expectedActions[1])
        expect(_.isEqual(store.getActions(), expectedActions)).to.equal(true)
      })
  })
})

我可能会注意到的另一件事是,我昨天进行了这个测试,但从那时起我修改了我的 Redux 状态的结构,并且似乎在这个过程中破坏了一些东西......:( 回顾我的 Git 历史并没有帮助我解决这个烦人的事情。

我希望有人能在这里为我指明正确的方向,这真的会帮助我和我内心的平静。提前致谢!

唉...我发现了我的愚蠢错误。 fetchMock.mock('http://test-teun.easyposonline.dev:3000/api/‌​v1/auth_tokens/creat‌​e', authTokenCreateSuccessfulResponse) 应该 fetchMock.mock('http://test-teun.easyposonline.dev:3000/api/‌​v1/auth_tokens/creat‌​e', authTokenCreateSuccessfulResponse.payload)