Cypress stub function gets lost after loading my app

Viewed 2433

In my main React app's class componentDidMount I call an api method to fetch some data. I'm trying to test that my app does the right thing given the data. Rather than try and mock the server, and deal with Cypress's semi-support for fetch and whatnot, I'm trying to cy.stub the entire API function to just return a block of data.

// api.ts

export const fetchData = async (): Promise<IData> => {
  ...
}
// app.tsx
import { fetchData } from "../api";

export class App extends React.PureComponent<IProps, IState> {

  async componentDidMount() {
     const data = await fetchData(); 
     // ...
  }
}
// testData.test.ts

import * as Api from "../../src/api";

context("Test the app after loading mock data from the API", () => {

  describe("Calling the API",() => {

    before(() => {
      cy.stub(Api, "fetchData", () => {
        return Promise.resolve({
          someData: "value"
        });
      });

      cy.visit("/");
    });

    it("calls 'fetchData'", () => {
      expect(Api.fetchData).to.be.called;
    });

  });
});

However, the app still calls the original version of fetchData instead of the stubbed version.

I tried experimenting by writing a test that simply calls a library method that itself imports fetchData, and that time the mock worked fine. So mocking an ES6 function that way should work. So it's something to do with loading my application that causes it to get lost.

2 Answers

This is not possible with cy.visit. You can use the new plugin @cypress/react to do the trick ;)

That's not really how the stubbing is supposed to work:

https://docs.cypress.io/guides/guides/network-requests.html#Stubbing

To begin stubbing responses you need to do two things.

Start a cy.server() Provide a cy.route()

cy.server()           // enable response stubbing
cy.route({
  method: 'GET',      // Route all GET requests
  url: '/users/*',    // that have a URL that matches '/users/*'
  response: []        // and force the response to be: []
})

Not sure which API call you're trying to do, but this is a great headstart, and it doesn't require to have cypress any knowledge of your internal api work.

Not really knowing what you are trying to test, but a complete example would be this:

describe("Calling the API",() => {

    cy.server()           // enable response stubbing
    cy.route({
      method: 'GET',      // Route all GET requests
      url: '/users/*',    // that have a URL that matches '/users/*'
      response: []        // and force the response to be: []
    })
    .as('get-user')
    .visit('/')
    .wait('@get-user')    // wait for your call to finish and assert it has been called

})
Related