Home > Blockchain >  Mock addListener from navigation in unit test
Mock addListener from navigation in unit test

Time:05-16

Used addListener from navigation like this,

useEffect(() => {
 const navigationSubscription = props.navigation.addListener(
   "willFocus",
   () => setFocused(true)
 );
 return navigationSubscription.remove; //navigationSubscription is undefined here.
}, []);

And here is the code snippet from test file,

const componentStub = (props) => {
  return (
    <Provider store={store}>
      <TestComponent            
        navigation={{
          navigate: jest.fn(),
          addListener: jest.fn().mockImplementation((event, callback) => {
            callback();
            //remove: jest.fn();
          }),
          canGoBack: jest.fn(),
          dispatch: jest.fn(),
          getParent: jest.fn(),
          getState: jest.fn(),
          goBack: jest.fn(),
          isFocused: jest.fn(),
          pop: jest.fn(),
          popToTop: jest.fn(),
          push: jest.fn(),
          removeListener: jest.fn(),
          replace: jest.fn(),
          reset: jest.fn(),
          setOptions: jest.fn(),
          setParams: jest.fn(),
          // remove: jest.fn(),
        }}
        {...props}
      />
    </Provider>
  );
};
describe("TestComponent unit tests", () => {
 it("Should render correctly", () => {
   let componentUtils = render(componentStub());
   const { toJSON } = componentUtils;
   expect(toJSON().children.length).toBeGreaterThan(0);
 });
});

I'm getting TypeError: Cannot read properties of undefined (reading remove)

CodePudding user response:

Maybe navigationSubscription not yet be assigned cause that error, to avoid i think make a condition before call:

useEffect(() => {
 const navigationSubscription = props.navigation.addListener(
   "willFocus",
   () => setFocused(true)
 );
 if(navigationSubscription){
    return navigationSubscription.remove; //<=== here. To surely: return navigationSubscription?.remove
  }
 
}, [props.navigation]); //<=== Then pass props.navigation to make component re-render when it change

CodePudding user response:

You have a small problem with mocked addListener. It's expecting a returned value when you call addListener, but you've not returned anything from that mocked function.

A potential fix could be

const componentStub = (props) => {
  return (
    <Provider store={store}>
      <TestComponent            
        navigation={{
          navigate: jest.fn(),
          addListener: jest.fn().mockImplementation((event, callback) => {
            callback();
            //returning value for `navigationSubscription`
            return {
               remove: jest.fn()
            }
          }),
          canGoBack: jest.fn(),
          dispatch: jest.fn(),
          getParent: jest.fn(),
          getState: jest.fn(),
          goBack: jest.fn(),
          isFocused: jest.fn(),
          pop: jest.fn(),
          popToTop: jest.fn(),
          push: jest.fn(),
          removeListener: jest.fn(),
          replace: jest.fn(),
          reset: jest.fn(),
          setOptions: jest.fn(),
          setParams: jest.fn(),
          // remove: jest.fn(),
        }}
        {...props}
      />
    </Provider>
  );
};
describe("TestComponent unit tests", () => {
 it("Should render correctly", () => {
   let componentUtils = render(componentStub());
   const { toJSON } = componentUtils;
   expect(toJSON().children.length).toBeGreaterThan(0);
 });
});
  • Related