title: Mocking RNCamera with Detox does not work, non-mock impl is called
body: <p>I'm trying to mock out RNCamera in a Detox test. However, the mock camera does not override the real implementation. </p>
  
  <p>I followed <a href="https://github.com/wix/Detox/blob/master/docs/Guide.Mocking.md" rel="nofollow noreferrer">these instructions</a> and incorporated advice <a href="https://stackoverflow.com/questions/54363389/followed-detox-mock-implementation-but-not-working">from</a> <a href="https://github.com/wix/Detox/issues/1116" rel="nofollow noreferrer">these</a> <a href="https://github.com/wix/Detox/issues/1289" rel="nofollow noreferrer">posts</a>. </p>
  
  <p>The result is: </p>
  
  <ul>
  <li>The mock camera class file itself <em>is</em> executed (top-level logging is printed)</li>
  <li>Mock camera's takePictureAsync and render functions are <em>not</em> called</li>
  <li>Emulator's default camera is used</li>
  </ul>
  
  <p>I have also tried:</p>
  
  <ul>
  <li><code>RN_SRC_EXT=e2e react-native run-android</code>, then <code>detox test</code></li>
  <li>adding <code>"test-runner": "jest" and calling</code>jest.mock` in the best body</li>
  <li>replacing <code>RN_SRC_EXT=e2e</code> with <code>RN_SRC_EXT=e2e.js</code></li>
  <li>cleanup: <code>rm -rf node_modules; yarn install</code> etc. </li>
  </ul>
  
  <p>My app layout is like (non-test-relevant content excluded):</p>
  
  <p><code>package.json</code>:</p>
  
  <pre><code>{
    ...
    "dependencies": {
      ...
      "@types/jest": "^24.0.21",
      "react": "16.9.0",
      "react-dom": "latest",
      "react-native": "0.61.1",
      "react-native-camera": "^3.6.0",
    },
    "devDependencies": {
      "@babel/core": "latest",
      "@babel/preset-env": "latest",
      "@babel/register": "latest",
      "@babel/preset-react": "latest",
      "@react-native-community/eslint-config": "^0.0.5",
      "babel-jest": "^24.9.0",
      "detox": "^14.5.1",
      "jest": "^24.9.0",
      "jest-fetch-mock": "^2.1.2",
      "metro-react-native-babel-preset": "^0.56.0",
      "mocha": "^6.2.2",
      "react-test-renderer": "16.9.0"
    },
    "detox": {
      "configurations": {
        "android.emu.debug": {
          "binaryPath": "android/app/build/outputs/apk/debug/app-debug.apk",
          "build": "RN_SRC_EXT=e2e cd android &amp;&amp; ./gradlew assembleDebug assembleAndroidTest -DtestBuildType=debug &amp;&amp; cd ..",
          "type": "android.emulator",
          "device": {
            "avdName": "Pixel_2_API_29"
          }
        },
        "android.emu.release": {
          "binaryPath": "android/app/build/outputs/apk/release/app-release.apk",
          "build": "RN_SRC_EXT=e2e cd android &amp;&amp; ./gradlew assembleRelease assembleAndroidTest -DtestBuildType=release &amp;&amp; cd ..",
          "type": "android.emulator",
          "device": {
            "avdName": "Pixel_2_API_29"
          }
        }
      }
    }
  }
  </code></pre>
  
  <p><code>e2e/config.js</code>:</p>
  
  <pre><code>require('@babel/register')({
      //cache: true,
      presets: [require('metro-react-native-babel-preset')],
      plugins: [require('@babel/plugin-transform-runtime').default],
      only: ['./e2e', './js'],
      ignore: ['node_modules']
    });
  </code></pre>
  
  <p><code>e2e/config.json</code>:</p>
  
  <pre><code>{
      "setupFilesAfterEnv": ["./init.js"],
      "testEnvironment": "node",
      "reporters": ["detox/runners/jest/streamlineReporter"],
      "testMatch": ["**/__tests__/**/*.js?(x)", "**/?(*.)(e2e).js?(x)"],
      "verbose": true
  }
  </code></pre>
  
  <p><code>e2e/mocha.opts</code>:</p>
  
  <pre><code>--recursive
  --timeout 300000
  --bail
  --file e2e/init.js
  --require e2e/config.js
  --require e2e/config.json
  --file e2e/react-native-camera.e2e.js
  </code></pre>
  
  <p><code>metro.config.js</code>:</p>
  
  <pre><code>const defaultSourceExts = require('metro-config/src/defaults/defaults').sourceExts
  module.exports = {
      transformer: {
          getTransformOptions: async () =&gt; ({
              transform: {
                  experimentalImportSupport: false,
                  inlineRequires: false,
              },
          }),
      },
      resolver: { 
          sourceExts: process.env.RN_SRC_EXT
                      ? process.env.RN_SRC_EXT.split(',').concat(defaultSourceExts)
                      : defaultSourceExts
        }
  };
  // printed as: module.exports.resolver from e2e { sourceExts: [ 'e2e', 'js', 'json', 'ts', 'tsx' ] }
  console.log("module.exports from e2e", module.exports);
  </code></pre>
  
  <p><code>e2e/config.json</code>:</p>
  
  <pre><code>{
      "setupFilesAfterEnv": ["./init.js"],
      "testEnvironment": "node",
      "reporters": ["detox/runners/jest/streamlineReporter"],
      // tried with and without this line
      "testMatch": ["**/__tests__/**/*.js?(x)", "**/?(*.)(e2e).js?(x)"],
      "verbose": true
  }
  </code></pre>
  
  <p><code>test.spec.js</code></p>
  
  <pre><code>describe('Example', () =&gt; {
    beforeEach(async () =&gt; {
        await device.reloadReactNative();
    });
  
    it('should blah blah balh', async () =&gt; {
        // test implementation
    });
   });
  </code></pre>
  
  <p><code>init.js</code>:</p>
  
  <pre><code>const detox = require('detox');
  const config = require('../package.json').detox;
  const adapter = require('detox/runners/mocha/adapter');
  
  before(async () =&gt; {
      await detox.init(config);
  });
  
  beforeEach(async function() {
      await adapter.beforeEach(this);
  });
  
  afterEach(async function() {
      await adapter.afterEach(this);
  });
  
  after(async () =&gt; {
      await detox.cleanup();
  });
  </code></pre>
  
  <p><code>e2e/react-native-camera.e2e.js</code>: (from <a href="https://github.com/react-native-community/react-native-camera/issues/1598" rel="nofollow noreferrer">here</a>)</p>
  
  <pre><code>import React from 'react';
  
  const timeout = ms =&gt; new Promise(resolve =&gt; setTimeout(resolve, ms));
  
  // This IS printed on detox test -c android.emu.debug.
  console.log("executing react-native-camera-e2e.js");
  export class RNCamera extends React.Component {
    static Constants = {
      Aspect: {},
      BarCodeType: {},
      Type: { back: 'back', front: 'front' },
      CaptureMode: {},
      CaptureTarget: {},
      CaptureQuality: {},
      Orientation: {},
      FlashMode: {},
      TorchMode: {},
    };
  
    takePictureAsync = async () =&gt; {
      console.log("mock RNCamera takePictureAsync"); // Never printed
      await timeout(2000);
      return {  uri: './static-image.jpg'  };
    };
  
    render() {
     // This is never printed.
      console.log("mock RNCamera render()");
      return null;
    }
  }
  
  export const takePictureAsync = async () =&gt; {
    console.log("mock RNCamera takePictureAsync"); // never printed
    await timeout(2000);
    return { uri: './static-image.jpg' };
  };
  
  
  export default RNCamera;
  </code></pre>