React-native-track-player: How to mock for tests?

Created on 19 Mar 2019  路  6Comments  路  Source: react-native-kit/react-native-track-player

There should be an example in the /example dir of how to mock the TrackPlayer for tests

I keep getting the error

Invariant Violation: Native module cannot be null.
      at invariant (node_modules/react-native/node_modules/fbjs/lib/invariant.js:40:15)
      at new invariant (node_modules/react-native/Libraries/EventEmitter/NativeEventEmitter.js:36:7)
      at Object.<anonymous> (node_modules/react-native-track-player/lib/index.js:5:45)
      at Object.<anonymous> (node_modules/react-native-track-player/index.js:4:1)

when trying to run a basic test

How do I mock the TrackPlayer for tests?

Thanks

Javascript

Most helpful comment

There might be a better way to do this as I'm new to Jest but this worked for me stub to get basic render tests passing

I have in myproj/jest/setup.js

jest.mock('react-native-track-player', () => {
  return {
    addEventListener: jest.fn(),
    registerEventHandler: jest.fn(),
    registerPlaybackService: jest.fn(),
    setupPlayer: jest.fn(),
    destroy: jest.fn(),
    updateOptions: jest.fn(),
    add: jest.fn(),
    remove: jest.fn(),
    skip: jest.fn(),
    skipToNext: jest.fn(),
    skipToPrevious: jest.fn(),
    removeUpcomingTracks: jest.fn(),
    // playback commands
    reset: jest.fn(),
    play: jest.fn(),
    pause: jest.fn(),
    stop: jest.fn(),
    seekTo: jest.fn(),
    setVolume: jest.fn(),
    setRate: jest.fn(),
    // player getters
    getQueue: jest.fn(),
    getTrack: jest.fn(),
    getCurrentTrack: jest.fn(),
    getVolume: jest.fn(),
    getDuration: jest.fn(),
    getPosition: jest.fn(),
    getBufferedPosition: jest.fn(),
    getState: jest.fn(),
    getRate: jest.fn(),
  };
});

and in myproj/package.json

  "jest": {
    "preset": "react-native",
    "setupFilesAfterEnv":  ["./jest/setup.js"]
  },

I think it would be hugely helpful to have an example of mocking the TrackPlayer in the /example directory of this project, and I'd be glad to open a PR for this if the maintainers like

All 6 comments

There might be a better way to do this as I'm new to Jest but this worked for me stub to get basic render tests passing

I have in myproj/jest/setup.js

jest.mock('react-native-track-player', () => {
  return {
    addEventListener: jest.fn(),
    registerEventHandler: jest.fn(),
    registerPlaybackService: jest.fn(),
    setupPlayer: jest.fn(),
    destroy: jest.fn(),
    updateOptions: jest.fn(),
    add: jest.fn(),
    remove: jest.fn(),
    skip: jest.fn(),
    skipToNext: jest.fn(),
    skipToPrevious: jest.fn(),
    removeUpcomingTracks: jest.fn(),
    // playback commands
    reset: jest.fn(),
    play: jest.fn(),
    pause: jest.fn(),
    stop: jest.fn(),
    seekTo: jest.fn(),
    setVolume: jest.fn(),
    setRate: jest.fn(),
    // player getters
    getQueue: jest.fn(),
    getTrack: jest.fn(),
    getCurrentTrack: jest.fn(),
    getVolume: jest.fn(),
    getDuration: jest.fn(),
    getPosition: jest.fn(),
    getBufferedPosition: jest.fn(),
    getState: jest.fn(),
    getRate: jest.fn(),
  };
});

and in myproj/package.json

  "jest": {
    "preset": "react-native",
    "setupFilesAfterEnv":  ["./jest/setup.js"]
  },

I think it would be hugely helpful to have an example of mocking the TrackPlayer in the /example directory of this project, and I'd be glad to open a PR for this if the maintainers like

Nice! And did you also have to manage this?

Test suite failed to run

    TypeError: Class extends value undefined is not a constructor or null

       6 | import Ctrl, { IProps, IState } from '../../controllers/player';
       7 |
    >  8 | class Player extends ProgressComponent<IProps, IState> {
         |                      ^
       9 |   public async componentDidMount() {
      10 |     await this.props.init();
      11 |   }

[UPDATE]

Oops, just add ProgressComponent: jest.fn(), did work.

Oops, just add ProgressComponent: jest.fn(), did work.

When I do it like that, i get an error:
TypeError: Class constructor AudioPlayerProgressBar cannot be invoked without 'new'

Where AudioPlayerProgressBar is the same as your Player

jest.mock('react-native-track-player', () => {
  return {
    // [...]
    ProgressComponent: jest.fn()
  };
});

Am I missing something?

Not sure, but see if this any of this can help

"jest": {
    "preset": "react-native",
    "setupFiles": [
      "<rootDir>/__tests__/setup.js"
    ],
    "globals": {
      "window": {}
    },
    "moduleFileExtensions": [
      "ts",
      "tsx",
      "js",
      "jsx",
      "json"
    ],
    "modulePaths": [
      "<rootDir>"
    ],
    "testRegex": "/__tests__/.*.test.(js|tsx|ts)?$",
    "transform": {
      "^.+\\.js$": "<rootDir>/node_modules/react-native/jest/preprocessor",
      "^.+\\.(js|jsx)?$": "<rootDir>/node_modules/babel-jest",
      "^.+\\.(ts|tsx)?$": "<rootDir>/node_modules/ts-jest"
    },
    "transformIgnorePatterns": [
      "node_modules/(?!((jest-)?react-native|react-navigation|@react-navigation/.*))"
    ]
  },

Plus, check if you don't have multiple jest config, for example; inside package.json and jest.config.js. I had and that took me some time to figure it out.

I struggled with this challenge earlier today. My solution:

jest-setup.js

import React from 'react'

class MockComponent extends React.Component {
  render() {
    return <>{this.props.children}</>
  }
}
{... other mocks}

jest.mock('react-native-track-player', () => {
  return {
    {... other mocks}
    ProgressComponent: () => MockComponent,
  }
})

Gladly welcome any improvements.

The problem I have is that if I add the mock to jest.setup.js then the mocks I do in my tests do not get applied so then I do not have full control over the tests. I don't think this solves it entirely.

Was this page helpful?
0 / 5 - 0 ratings