[英]How do I test component methods on a React component that are defined as arrow functions (class properties)?
I am able to test class methods just fine by using spies and Component.prototype
. 我可以通过使用spies和
Component.prototype
来测试类方法。 However, many of my class methods are class properties because I need to use this
(for this.setState
, etc.), and since binding in the constructor is very tedious and looks ugly, using arrow functions is much better in my opinion. 但是,我的许多类方法都是类属性,因为我需要使用
this
(对于this.setState
等),并且因为构造函数中的绑定非常繁琐且看起来很丑,所以在我看来使用箭头函数要好得多。 The components I have built using class properties work in the browser, so I know my babel config is correct. 我使用类属性构建的组件在浏览器中工作,所以我知道我的babel配置是正确的。 Below is the component I am trying to test:
以下是我要测试的组件:
//Chat.js
import React from 'react';
import { connect } from 'react-redux';
import { fetchThreadById, passMessageToRedux } from '../actions/social';
import withLogin from './hoc/withLogin';
import withTargetUser from './hoc/withTargetUser';
import withSocket from './hoc/withSocket';
import ChatMessagesList from './ChatMessagesList';
import ChatForm from './ChatForm';
export class Chat extends React.Component {
state = {
messages : [],
};
componentDidMount() {
const { auth, targetUser, fetchThreadById, passMessageToRedux } = this.props;
const threadId = this.sortIds(auth._id, targetUser._id);
//Using the exact same naming scheme for the socket.io rooms as the client-side threads here
const roomId = threadId;
fetchThreadById(threadId);
const socket = this.props.socket;
socket.on('connect', () => {
console.log(socket.id);
socket.emit('join room', roomId);
});
socket.on('chat message', message => passMessageToRedux(message));
//socket.on('chat message', message => {
// console.log(message);
// this.setState(prevState => ({ messages: [ ...prevState.messages, message ] }));
//});
}
sortIds = (a, b) => (a < b ? `${a}_${b}` : `${b}_${a}`);
render() {
const { messages, targetUser } = this.props;
return (
<div className='chat'>
<h1>Du snakker med {targetUser.social.chatName || targetUser.info.displayName}</h1>
<ChatMessagesList messages={messages} />
<ChatForm socket={this.props.socket} />
</div>
);
}
}
const mapStateToProps = ({ chat: { messages } }) => ({ messages });
const mapDispatchToProps = dispatch => ({
fetchThreadById : id => dispatch(fetchThreadById(id)),
passMessageToRedux : message => dispatch(passMessageToRedux(message)),
});
export default withLogin(
withTargetUser(withSocket(connect(mapStateToProps, mapDispatchToProps)(Chat))),
);
Chat.defaultProps = {
messages : [],
};
And here is the test file: 这是测试文件:
//Chat.test.js
import React from 'react';
import { shallow } from 'enzyme';
import { Server, SocketIO } from 'mock-socket';
import { Chat } from '../Chat';
import users from '../../fixtures/users';
import chatMessages from '../../fixtures/messages';
let props,
auth,
targetUser,
fetchThreadById,
passMessageToRedux,
socket,
messages,
wrapper,
mockServer,
spy;
beforeEach(() => {
window.io = SocketIO;
mockServer = new Server('http://localhost:5000');
mockServer.on('connection', server => {
mockServer.emit('chat message', chatMessages[0]);
});
auth = users[0];
messages = [ chatMessages[0], chatMessages[1] ];
targetUser = users[1];
fetchThreadById = jest.fn();
passMessageToRedux = jest.fn();
socket = new io('http://localhost:5000');
props = {
mockServer,
auth,
messages,
targetUser,
fetchThreadById,
passMessageToRedux,
socket,
};
});
afterEach(() => {
mockServer.close();
jest.clearAllMocks();
});
test('Chat renders correctly', () => {
const wrapper = shallow(<Chat {...props} />);
expect(wrapper).toMatchSnapshot();
});
test('Chat calls fetchThreadById in componentDidMount', () => {
const wrapper = shallow(<Chat {...props} />);
const getThreadId = (a, b) => (a > b ? `${b}_${a}` : `${a}_${b}`);
const threadId = getThreadId(auth._id, targetUser._id);
expect(fetchThreadById).toHaveBeenLastCalledWith(threadId);
});
test('Chat calls componentDidMount', () => {
spy = jest.spyOn(Chat.prototype, 'componentDidMount');
const wrapper = shallow(<Chat {...props} />);
expect(spy).toHaveBeenCalled();
});
test('sortIds correctly sorts ids and returns threadId', () => {
spy = jest.spyOn(Chat.prototype, 'sortIds');
const wrapper = shallow(<Chat {...props} />);
expect(spy).toHaveBeenCalled();
});
The second to last test which checks if componentDidMount
(not a class method) was called runs with no errors, as do all the other tests except the last one. 检测是否调用
componentDidMount
(不是类方法)的倒数第二个测试运行没有错误,除了最后一个测试之外的所有其他测试都是如此。 For the last test, Jest gives me the following error: 对于最后一次测试,Jest给出了以下错误:
FAIL src\components\tests\Chat.test.js
● sortIds correctly sorts ids and returns threadId
Cannot spy the sortIds property because it is not a function; undefined given instead
65 |
66 | test('sortIds correctly sorts ids and returns threadId', () => {
> 67 | spy = jest.spyOn(Chat.prototype, 'sortIds');
68 | const wrapper = shallow(<Chat {...props} />);
69 | expect(spy).toHaveBeenCalled();
70 | });
at ModuleMockerClass.spyOn (node_modules/jest-mock/build/index.js:699:15)
at Object.<anonymous> (src/components/tests/Chat.test.js:67:16)
I have been told that I can use mount
from enzyme instead of shallow
and then use Chat.instance
instead of Chat.prototype
, but to my understanding, if I do so, enzyme will also render Chat
's children, and I certainly do not want that. 我被告知我可以使用来自酶而不是
shallow
mount
然后使用Chat.instance
而不是Chat.prototype
,但据我了解,如果我这样做,酶也会渲染Chat
的孩子,我当然不会想要那个。 I actually tried using mount
, but then Jest started complaining about connect(ChatForm)
not having store
in either its context or props ( ChatForm
is connected to redux, but I like to test my redux-connected components by importing the non-connected component and mocking a redux store). 我实际上尝试使用
mount
,但随后Jest开始抱怨connect(ChatForm)
没有在其上下文或道具中store
( ChatForm
连接到redux,但我喜欢通过导入非连接组件来测试我的redux连接组件,嘲笑redux商店)。 Does anyone know how to test class properties on React components with Jest and Enzyme? 有谁知道如何使用Jest和Enzyme测试React组件的类属性? Thanks a bunch in advance!
提前谢谢!
Even if the rendering is shallow, you can call the wrapper.instance()
method. 即使渲染很浅,也可以调用
wrapper.instance()
方法。
it("should call sort ids", () => {
const wrapper = shallow(<Chat />);
wrapper.instance().sortIds = jest.fn();
wrapper.update(); // Force re-rendering
wrapper.instance().componentDidMount();
expect(wrapper.instance().sortIds).toBeCalled();
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.