I want to test the post request for fetch API which is initiated on clicking a button. To mock the fetch api request, I am using the sinon
library. The fake server is live but does not provide a response JSON object. The apiUrl
here is http://localhost:5000/api/users
and the userData is { sid: 1, sname: 'test'}
.
Here is the App.test.js file
describe('test api',()=>{
let server;
beforeEach(() => {
server = fakeServer.create();
server.respondWith('POST',
apiUrl,
[
200,
{ 'Content-Type': 'application/json' },
JSON.stringify(userData)
]
);
});
describe('app component', () => {
const app = mount(<App />);
beforeEach(() => {
app.find('Button').simulate('click');
});
it('get data from server', done => {
server.respond();
setTimeout(done);
});
it('updates state', () => {
expect(app.state().user).toEqual('user1') // fails
})
});
});
Edited:
App Component
class App extends Component {
constructor() {
super();
this.state = {
serialNum: ''
user: ''
}
}
submitUrl = async () => {
const postData = { sid: this.state.serialNum, sname: 'something'};
try {
let response = await fetch('http://localhost:5000/api/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(postData)
});
response = await response.json();
if (result) {
this.setState({ user: response.username});
}
} catch (err) {
console.log('Error:', err);
}
}
render() {
return (
<div className="container">
<div className="col">
<Form>
<FormGroup>
<div className="row input-container">
<FormControl placeholder="Enter value"
onChange={(e) => this.setState({
serialNum: e.target.value
})} />
</div>
<div className="row">
<Button variant="primary"
className="submit-btn"
onClick={this.submitUrl}>Submit</Button>
</div>
</FormGroup>
</Form>
</div>
</div>
);
}
}
export default App;
What am I missing here? How do I debug if the server request has succeeded or failed? I am calling server.respond()
after simulating the button click and also asking Jest to wait till the server completes request by passing done
parameter.
Why not just mock the fetch function itself, instead of the server. So:
describe('app component', () => {
const app = mount(<App />);
beforeEach(() => {
global.fetch = jest.fn().mockImplementation(() => {
return Promise.resolve(new Response(JSON.stringify({ sid: 1, sname: 'test' })));
});
app.find('Button').simulate('click');
});
it('updates state', () => {
expect(app.state().user).toEqual('user1') // fails
})
});
Remember that you are testing your state change here after a data fetch, just mocking the fetch function should be enough to test your logic sufficiently.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With