Reputation: 305
I want to test that a class method is called on 'mousedown' event. Please take a look on the code below.
This is my component:
import React, { Component } from 'react';
import styled from 'styled-components';
import MyChildClass from './MyChildClass';
export default class MyClass extends Component {
constructor(props) {
super(props);
// Init state
this.state = {
balls: []
};
this.onMouseUpHandler = this.onMouseUpHandler.bind(this, this.state.balls);
}
onMouseDownHandler = (balls, e) => {
...
};
render() {
return (
<StyledEnvironment className='wrapper'>
<div
onMouseDown={this.onMouseDownHandler}
onMouseUp={this.onMouseUpHandler}
>
{balls}
</div>
</StyledEnvironment>
);
}
And this is my test:
import React from 'react';
import { mount, shallow } from 'enzyme';
import MyClass from '../MyClass';
it('should call onMouseDownHandler on mouse down', () => {
//...arrange
const instance = component.instance();
const wrapper = component.find('.wrapper').at(0);
instance.setMousePosition = jest.fn();
instance.onMouseDownHandler = jest.fn();
instance.forceUpdate();
component.update();
//...act
wrapper.simulate('mouseDown');
//...assert
expect(instance.onMouseDownHandler).toHaveBeenCalled();
});
So, I eventually expect the test to pass, but still the runner returns fail, with message
Expected mock function to have been called, but it was not called.
I've gone through many examples on Google, and found out that this is proper pattern of testing events.
Upvotes: 0
Views: 530
Reputation: 102557
Use arrow function as the method of class is not easy to test. Because it will be used as property of class, not instance method of class. So I suggest you refactor the method.
After refactoring, you can use jest.spyOn(object, methodName) to spy on the onMouseDownHandler
method.
For example,
index.tsx
:
import React, { Component } from 'react';
const StyledEnvironment = ({ children, className }) => <div className={className}>{children}</div>;
export default class MyClass extends Component<any, any> {
constructor(props) {
super(props);
this.state = {
balls: []
};
}
onMouseDownHandler(balls, e) {
// TBD
}
onMouseUpHandler(balls, e) {
// TBD
}
render() {
return (
<StyledEnvironment className="wrapper">
<div
onMouseDown={e => this.onMouseDownHandler(this.state.balls, e)}
onMouseUp={e => this.onMouseUpHandler(this.state.balls, e)}>
{this.state.balls}
</div>
</StyledEnvironment>
);
}
}
index.spec.tsx
:
import React from 'react';
import { shallow } from 'enzyme';
import MyClass from './';
describe('MyClass', () => {
test('should handle mousedown event', () => {
const wrapper = shallow(<MyClass></MyClass>);
const onMouseDownHandlerSpy = jest.spyOn(MyClass.prototype, 'onMouseDownHandler');
wrapper.find('div').simulate('mouseDown');
expect(onMouseDownHandlerSpy).toBeCalled();
});
});
Unit test result with coverage report:
PASS src/stackoverflow/58652312/index.spec.tsx
MyClass
✓ should handle mousedown event (12ms)
-----------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
-----------|----------|----------|----------|----------|-------------------|
All files | 76.47 | 100 | 62.5 | 91.67 | |
index.tsx | 76.47 | 100 | 62.5 | 91.67 | 25 |
-----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 4.951s, estimated 9s
Source code: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/58652312
Upvotes: 1