为啥这些 Jest 测试失败了? TypeError:无法读取未定义的属性“应用”
Posted
技术标签:
【中文标题】为啥这些 Jest 测试失败了? TypeError:无法读取未定义的属性“应用”【英文标题】:Why are these Jest tests failing? TypeError: Cannot read property 'apply' of undefined为什么这些 Jest 测试失败了? TypeError:无法读取未定义的属性“应用” 【发布时间】:2017-11-15 08:56:00 【问题描述】:我有 2 个组件/测试 Login.js 和 Routes.js 都有相同的错误:
TypeError:无法读取未定义的属性“应用”
不确定要在此处应用什么...
组件
登录.js
import React from 'react'
import connect from "react-redux"
import bindActionCreators from 'redux';
import setCurrentUser from '../../actions/authActions'
import * as api from '../../services/api'
import Notification from '../common/Notification'
const mapDispatchToProps = (dispatch) =>
return
setUser: (user) =>
bindActionCreators(setCurrentUser(user), dispatch)
;
export class LoginContainer extends React.Component
constructor(props)
super(props)
this.state = ;
this.handleSubmit = this.handleSubmit.bind(this);
handleSubmit(e)
...
render()
return (
<div className="app-bg">
...
</div>
)
export default connect(null, mapDispatchToProps)(LoginContainer);
Routes.js
import React from 'react'
import Route, Switch from 'react-router-dom'
import LoginContainer from './auth/Login'
import Dashboard from './Dashboard'
import NoMatch from './NoMatch'
const Routes = () =>
return (
<Switch>
<Route exact= true path="/" component= LoginContainer />
<Route path="/dashboard" component= Dashboard />
<Route component= NoMatch />
</Switch>
);
export default Routes
测试
登录测试
import React from 'react'
import Provider from "react-redux"
import ReactTestUtils from 'react-dom/test-utils'
import createCommonStore from "../../store";
import mount, shallow from 'enzyme'
import toJson from 'enzyme-to-json'
import missingLogin from '../../consts/errors'
// import Login from './Login'
import LoginContainer as Login from './Login';
import Notification from '../common/Notification'
const store = createCommonStore();
const user =
id: 1,
role: 'Admin',
username: 'leongaban'
;
const loginComponent = shallow(
<Provider store=store>
<LoginContainer/>
</Provider>
);
const fakeEvent = preventDefault: () => '' ;
describe('<Login /> component', () =>
it('should render', () =>
const tree = toJson(loginComponent);
expect(tree).toMatchSnapshot();
);
it('should contains the words "Forgot Password"', () =>
expect(loginComponent.contains('Forgot Password')).toBe(true);
);
it('should render the Notification component if state.error is true', () =>
loginComponent.setState( error: true );
expect(loginComponent.find(Notification).length).toBe(1);
);
);
Routes.test
import React from 'react'
import Provider from "react-redux"
import mount, shallow from 'enzyme'
import MemoryRouter from 'react-router'
import createCommonStore from "../store";
import toJson from 'enzyme-to-json'
import Routes from './Routes'
import Login from './auth/Login'
import Dashboard from './Dashboard'
import NoMatch from './NoMatch'
const store = createCommonStore();
const routesMount = (path) =>
return mount(
<Provider store=store>
<MemoryRouter initialEntries=[ path ] initialIndex=0>
<Routes />
</MemoryRouter>
</Provider>
);
;
describe('<Routes /> component', () =>
it('should save a snapshot', () =>
const routesComponent = shallow(<Routes />);
const tree = toJson(routesComponent);
expect(tree).toMatchSnapshot();
);
it('should render Login component when visiting /', () =>
const routesComponent = routesMount('/');
expect(routesComponent.find(Login).length).toBe(1);
);
it('should render Dashboard component when visiting /dashboard', () =>
const routesComponent = routesMount('/dashboard');
expect(routesComponent.find(Dashboard).length).toBe(1);
);
it('should render the NoMatch component when visiting invalid path', () =>
const routesComponent = routesMount('/404');
expect(routesComponent.find(NoMatch).length).toBe(1);
);
);
商店
store.js
The Redux Chrome pluginwindow.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
import React from "react"
import applyMiddleware, combineReducers, compose, createStore from "redux"
import thunk from "redux-thunk"
import userReducer from "./reducers/UserReducer"
import authReducer from "./reducers/AuthReducer"
export const createCommonStore = (trackStore=false) =>
const reducers = combineReducers(
user: userReducer,
user: authReducer
);
//noinspection JSUnresolvedVariable
const store = createStore(reducers,
compose(
applyMiddleware(thunk),
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
)
);
if (trackStore)
store.subscribe((() =>
console.log(" store changed", store.getState());
));
return store;
;
【问题讨论】:
您也可以发布store.js
脚本吗?那里好像出了什么问题。
@Tiddo defs!添加了商店代码...
我不是 100% 确定,但我有一种预感,`window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()` 会导致 undefined
,并导致错误。您可以尝试删除该行并查看它是否仍然失败?
啊!有趣......是的,就是这样......嗯。好的,所以我需要该逻辑才能使 chrome devtools 中的 Redux 选项卡正常工作。有没有办法在开玩笑的测试中以某种方式忽略它?
或者更好:按照扩展程序本身的高级设置说明进行操作here
【参考方案1】:
在store.js
中,表达式window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
的计算结果为undefined
。这会导致compose
中的错误。插件文档有 solution :
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(reducers,
composeEnhancers(
applyMiddleware(thunk),
)
);
【讨论】:
以上是关于为啥这些 Jest 测试失败了? TypeError:无法读取未定义的属性“应用”的主要内容,如果未能解决你的问题,请参考以下文章
为啥 Jest 不让我使用节点测试环境,即使他们自己更改了它?
用 Jest 测试 Vue 失败,Jest 遇到了意外的令牌,SyntaxError: Unexpected token import