Testing with Jest & Enzyme
When should we write tests?
- Unit Test as a bug Report
- Unit Test as a feature documentation
- Code design
- Developer understanding
Test Component
What should we test?
What should we test?
- The real DOM (Given props and state does it render the right thing?)
- Events (Are the events fired?)
- State changes (Are the state transitions correct?)
Testing DOM
class Button extends Component {
render(){
returns(
<button>{ this.props.text }</button>
);
}
}
Test
import Button from './Button';
describe('<Button />', () => {
it('should render a button with the right text', () => {
const wrapper = mount(<Button text='mycs' />);
expect(wrapper.find('button').text()).toBe('mycs');
});
}
Component
Testing Events
class Button extends Component {
onClickHandler(e){
this.props.onClick(e);
}
render(){
returns(
<button onClick={ e => this.onClickHandler(e) }>
{ this.props.text }
</button>
);
}
}
Test
it('should call the passed onClick callback', () => {
const onButtonClick = jest.fn();
const wrapper = mount(
<Button onClick={onButtonClick} />
);
wrapper.find('button').simulate('click');
expect(onClickCallback).toHaveBeenCalled();
});
Component
Testing State Transitions
class Button extends Component {
...
onClickHandler(e){
this.setState({ angularSucks: true });
}
render(){
returns(
<button onClick={ e => this.onClickHandler(e) }>
{ this.props.text }
</button>
);
}
}
Test
it('should call the passed onClick callback', () => {
const onButtonClick = jest.fn();
const wrapper = mount(
<Button onClick={onButtonClick} />
);
wrapper.find('button').simulate('click');
expect(wrapper.state().angularSucks).toBeTruthy();
});
Component
Mock Functions / Classes
// Function
const func = jest.fn();
const func2 = jest.fn().mockImplementation(() => 42);
// Reset mocks
func.mockReset(); // To avoid affecting another test
// Class
SomeClass.mockImplementation(() => {
return {
m: mMock
}
})
const some = new SomeClass()
some.m('a', 'b')
console.log('Calls to m: ', mMock.mock.calls)
Component
Mock Modules
__mocks__/AuthService.js
Folder structure
SaveDesign.jest.jsx
Automatic mocks
Mock Modules
SaveDesign.jest.jsx
Automatic mocks
Test function without instantiating Component
// Component
class MyComponent extends Component{
...
calculateBboxes(mappingStructure){
...
}
...
}
// Test
import MyComponent from './MyComponent';
it('should calculate BBoxes', () => {
const boxes = MyComponent.prototype.calculateBboxes(mockMappingStructure);
expect(boxes).toEqual(expectedResult);
});
Update props, mock instance function
it('should re-initialize the canvas when props are updating', () => {
const wrapper = mount(<BboxOverlay mappingStructure={mappingStructure} );
wrapper.instance().initCanvas = jest.fn();
wrapper.setProps({something: 5});
expect(wrapper.instance().initCanvas).toHaveBeenCalled();
});
Component
Test scripts
- npm run jest // spawns parallel test runs
- npm run jest:notify // notify when test run finish
- npm run jest:ci // run test in sequense
- npm run jest filename.js // run single test file
Code coverage
Everytime you run jest a coverage folder is generated, open index.html to see your code coverage
100% Code coverage doesnt mean that your test is meaningfull
const func(){
return 10;
}
it('should return 10', () => {
func(); // Istanbul will report 100% code coverage
expect(true).toBe(true);
});
Review your tests
Review others' tests in PR reviews
Include your code coverage in your PR
Maybe a tool would help?
Thanks
Testing with Jest & Enzyme
By Avraam Mavridis
Testing with Jest & Enzyme
- 1,063