反应单元测试“不是函数”对象。<anonymous>

问题描述 投票:0回答:1

努力为使用 redux/sagas 的文件编写一些单元测试。

app.tsx
文件看起来像这样

import React, { StrictMode } from 'react'
import ReactDOM from 'react-dom'
import { Provider } from 'react-redux'
import { Router } from 'react-router-dom'
import App from './App'
import { injectStore } from './network/webapi-axios-interceptor'
import { history } from './helpers/history'
import './index.css'
import * as serviceWorker from './serviceWorker'
import configureStore from './store'

export const store = configureStore({})
injectStore(store)

ReactDOM.render(
  <Provider store={store}>
    <Router history={history}>
      <StrictMode>
        <App />
      </StrictMode>
    </Router>
  </Provider>,
  document.getElementById('root')
)

webapi-axios-interceptor.tsx
文件

import { AxiosInstance, InternalAxiosRequestConfig } from 'axios'
import { Header } from '../constants'

let store: any

export const injectStore = (_store: any) => {
  store = _store
}

function axiosInterceptor(instance: AxiosInstance): any {
  return instance.interceptors.request.use(
    (request) => axiosRequest(request),
    (error) => axiosRequestError(error?.message, error)
  )
}

function axiosRequest(
  request: InternalAxiosRequestConfig
): InternalAxiosRequestConfig | Promise<InternalAxiosRequestConfig> {
  if(request.headers) 
  request.headers = store.getState().config.config.currentUser
  return request
}

function axiosRequestError(
  message: string, 
  error?: any
): Promise<any> {
  return Promise.reject(error || message)
}

export default axiosInterceptor

和测试文件

tab.test.tsx
:

import React from 'react'
import { render } from '@testing-library/react'
import { mock } from '../__mock__/mock'
import Tab from '../Tab'
import configureStore from '../../../../../store'
import { Provider } from 'react-redux';
import { injectStore } from '../../../../../network/webapi-axios-interceptor'

describe('Tab', () => {
  beforeEach(() => {
   jest.resetAllMocks();
  })

  it('should render "Tab" component', () => {
    const store = configureStore({})
    injectStore(store)

    const result = render(
      <Provider store={store}>
        <Tab
          key={mock.key}
          onSuccessfulMerge={jest.fn()}
        />
      </Provider>
    )

   expect(result).toBeInTheDocument()
  })
})

尝试运行测试文件时出现以下错误:

 FAIL  src/pages/Customer/containers/Tab/__tests__/tab.test.tsx
  ● Test suite failed to run

    TypeError: (0 , _webapiAxiosInterceptor.injectStore) is not a function

      12 |
      13 | export const store = configureStore({})
    > 14 | injectStore(store)
         |            ^
      15 |
      16 | ReactDOM.render(
      17 |   <Provider store={store}>
      at Object.<anonymous> (src/index.tsx:14:12)
      at Object.<anonymous> (src/configuration/forms/options/standard-rejection-reasons.ts:1:2)
      at Object.<anonymous> (src/configuration/forms/fields.ts:4:1)      
      at Object.<anonymous> (src/configuration/forms/configuration.ts:2:1)
      at Object.<anonymous> (src/pages/Customer/containers/Form/Form.tsx:16:1)
      at Object.<anonymous> (src/pages/Customer/containers/Tab/Tab.tsx:43:1)
      at Object.<anonymous> (src/pages/Customer/containers/Tab/__tests__/tab.test.tsx:4:1)
      at TestScheduler.scheduleTests (node_modules/react-scripts/node_modules/@jest/core/build/TestScheduler.js:333:13)
      at runJest (node_modules/react-scripts/node_modules/@jest/core/build/runJest.js:404:19)

Test Suites: 1 failed, 1 total
Tests:       0 total
Snapshots:   0 total
Time:        8.732 s
Ran all test suites related to changed files.

有人可以帮忙吗?我是刚测试 redux/sagas 的新手,不幸的是我独自留在团队中。

在测试中,从接收 app.tsx 文件的同一位置存储

injectStore
如果需要,这是configureStore函数:

import { createStore, Store, compose, applyMiddleware } from 'redux'
import createSagaMiddleware, { END } from 'redux-saga'
import { createEpicMiddleware } from 'redux-observable'
import { rootReducer } from './rootReducer'
import { rootSaga } from './rootSaga'
import { rootEpic } from './rootEpic'
import { configFetchStarted } from './actions/configActions'


interface IExtendedStore extends Store {
  runSaga: any
  runEpic: any
  close: () => void
}

export default function configureStore(initialState: any) {
  const sagaMiddleware = createSagaMiddleware()
  const epicMiddleware = createEpicMiddleware()

  const composeEnhancers =
    typeof window === 'object' &&
    (window as any).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
      ? (window as any).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({})
      : compose

  const enhancer = composeEnhancers(
    applyMiddleware(sagaMiddleware, epicMiddleware)
  )

  const store = createStore(
    rootReducer(),
    initialState,
    enhancer
  ) as IExtendedStore

  store.runSaga = sagaMiddleware.run
  store.runEpic = epicMiddleware.run
  store.close = () => store.dispatch(END as any)
  store.runSaga(rootSaga)
  store.runEpic(rootEpic)
  store.dispatch(configFetchStarted())

  return store
}
reactjs redux jestjs
1个回答
0
投票

发现问题了。 原来是因为

export const injectStore = (_store: any) => {
  store = _store
}

axiosInterceptor
axiosRequest
位于同一文件中。

一旦我移入不同的文件,并使用该文件导入

app.tsx
,如下所示:

// inject-store.ts 
let store: any

const injectStore = (_store: any) => {
  store = _store
}

export default injectStore
 // app.tsx
    import React, { StrictMode } from 'react'
    import ReactDOM from 'react-dom'
    import { Provider } from 'react-redux'
    import { Router } from 'react-router-dom'
    import App from './App'
    import { injectStore } from './network/inject-store' // separate file from `webapi-axios-interceptor`
    import { history } from './helpers/history'
    import './index.css'
    import * as serviceWorker from './serviceWorker'
    import configureStore from './store'

    export const store = configureStore({})
    injectStore(store)

    ReactDOM.render(
      <Provider store={store}>
        <Router history={history}>
          <StrictMode>
            <App />
          </StrictMode>
        </Router>
      </Provider>,
      document.getElementById('root')
    )

问题解决了

© www.soinside.com 2019 - 2024. All rights reserved.