Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mocking fetch API for POST request using sinon, jest for react.js application

Tags:

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.

like image 200
MelDsz Avatar asked Sep 27 '19 16:09

MelDsz


1 Answers

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.

like image 89
etarhan Avatar answered Nov 15 '22 05:11

etarhan