Having very simple ponent:
import PropTypes from 'prop-types' import React from 'react' import { connect } from 'react-redux'
class MyComponent extends React.Component {
ponentWillMount() {
if (this.props.shouldDoSth) {
this.props.doSth()
}
}
render () {
return null
}
}
MyComponent.propTypes = {
doSth: PropTypes.func.isRequired,
shouldDoSth: PropTypes.bool.isRequired
}
const mapStateToProps = (state) => {
return {
shouldDoSth: state.shouldDoSth,
}
}
const mapDispatchToProps = (dispatch) => ({
doSth: () => console.log('you should not see me')
})
export default connect(mapStateToProps, mapDispatchToProps)(MyComponent)
I want to test if doSth
is called when shouldDoSth
is equal true
.
I've written a test:
describe('call doSth when shouldDoSth', () => {
it('calls doSth', () => {
const doSthMock = jest.fn()
const store = mockStore({shouldDoSth: true})
shallow(<MyComponent doSth={doSthMock}/>, { context: { store } }).dive()
expect(doSthMock).toHaveBeenCalled()
})
})
but it seems that although I pass doSth as props it gets overridden by mapDispatchToProps
as console.log('im not a mock')
is executed.
How to properly pass/override/assign doSth
function to make ponent use mock instead of function from mapDispatchToProps
. Or maybe I'm doing something which should not be allowed at all and there is 'proper' way of testing my case. Shall I just mock dispatch instead and check if it is called with proper arguments?
Having very simple ponent:
import PropTypes from 'prop-types' import React from 'react' import { connect } from 'react-redux'
class MyComponent extends React.Component {
ponentWillMount() {
if (this.props.shouldDoSth) {
this.props.doSth()
}
}
render () {
return null
}
}
MyComponent.propTypes = {
doSth: PropTypes.func.isRequired,
shouldDoSth: PropTypes.bool.isRequired
}
const mapStateToProps = (state) => {
return {
shouldDoSth: state.shouldDoSth,
}
}
const mapDispatchToProps = (dispatch) => ({
doSth: () => console.log('you should not see me')
})
export default connect(mapStateToProps, mapDispatchToProps)(MyComponent)
I want to test if doSth
is called when shouldDoSth
is equal true
.
I've written a test:
describe('call doSth when shouldDoSth', () => {
it('calls doSth', () => {
const doSthMock = jest.fn()
const store = mockStore({shouldDoSth: true})
shallow(<MyComponent doSth={doSthMock}/>, { context: { store } }).dive()
expect(doSthMock).toHaveBeenCalled()
})
})
but it seems that although I pass doSth as props it gets overridden by mapDispatchToProps
as console.log('im not a mock')
is executed.
How to properly pass/override/assign doSth
function to make ponent use mock instead of function from mapDispatchToProps
. Or maybe I'm doing something which should not be allowed at all and there is 'proper' way of testing my case. Shall I just mock dispatch instead and check if it is called with proper arguments?
3 Answers
Reset to default 3I think one thing you need to figure out is whether you want doSth
to be a prop, or a redux action connected in mapDispatchToProps.
If it's a prop, then you would connect it to redux in a parent (container). Remove it from this ponent's mapDispatchToProps. This would make the ponent more testable.
If you want it to be a redux action connected in this ponent, then it would make sense to move the action out of this ponent, somewhere like actions.js
, import it in this ponent, and then mock it in the test jest.mock('actions.js', () => ({doSth: jest.mock()}))
Export the unconnected ponent and use it in the test and you will be able to override the mapDispatchToProps action.
export class MyComponent extends React.Component {
ponentWillMount() {
if (this.props.shouldDoSth) {
this.props.doSth()
}
}
render () {
return null
}
}
MyComponent.propTypes = {
doSth: PropTypes.func.isRequired,
shouldDoSth: PropTypes.bool.isRequired
}
const mapStateToProps = (state) => {
return {
shouldDoSth: state.shouldDoSth,
}
}
const mapDispatchToProps = (dispatch) => ({
doSth: () => console.log('you should not see me')
})
export default connect(mapStateToProps, mapDispatchToProps)(MyComponent)
import {MyComponent} from '../MyComponent'
describe('call doSth when shouldDoSth', () => {
it('calls doSth', () => {
const doSthMock = jest.fn()
const store = mockStore({shouldDoSth: true})
shallow(<MyComponent doSth={doSthMock}/>, { context: { store } }).dive()
expect(doSthMock).toHaveBeenCalled()
})
})
I think that you should ask yourself if you want to test the unconnected MyComponent or the connected one.
Here you have two discussions that may help you: Am I testing connected ponents correclty? and Can't reference containers wrapped in a Provider or by connect with Enzyme
If you are not testing the action nor state properly said, you might forget about mapStateToProps and mapDispatchToProps (those processes are already tested by redux) and pass values through props.
Check the following example:
describe('MyComponent', () => {
let wrapper;
const doSthMock = jest.fn();
beforeEach(() => {
const ponentProps = {
doSth: true,
};
wrapper = mount(
<MyComponent
{... ponentProps}
doSth={doSthMock}
/>
);
});
it('+++ render the ponent', () => {
expect(wrapper.length).toEqual(1);
});
it('+++ call doSth when shouldDoSth', () => {
expect(doSthMock).toHaveBeenCalled();
});
})