Writing unit test for react-native native android methods
Asked Answered
T

1

8

I'm building react-native app which has some native android modules in it.
In MainApplication.java,

protected List<ReactPackage> getPackages() {
    return Arrays.<ReactPackage>asList(
        new VectorIconsPackage(),
        new MyCustomPackage()
    );
  }

In my MyCustomPackage,

public class MyCustomPackage implements ReactPackage {

  @Override
  public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
    return Collections.emptyList();
  }

  @Override
  public List<NativeModule> createNativeModules(
                              ReactApplicationContext reactContext) {
    List<NativeModule> modules = new ArrayList<>();

    modules.add(new MyCustomModule(reactContext));

    return modules;
  }

}

I have few other modules but this is an example. The all functions works well. Now I want to write unit test to methods which are in the MyCustomModule java class. I try to use Robolectric framework but don't know how it's working with react native. Is there any other tool for that? Can anyone give me some example or guide in writing unit test for react-native native android code?

Taste answered 22/4, 2018 at 3:45 Comment(2)
Already found a solution?Veery
No. Still not found a solution.Taste
S
2

Using Robolectric 4.

See my comments.

The way I do it is

  1. mock the Application in order to remove incompatible dependency loading.
  2. wrap the ApplicationContext in ReactApplicationContext to instantiate the module.

The @Config and custom Application stuffs are probably required to remove binary dependencies not handled by robolectric such as Bugsnag and the general soloader. Could perhaps work without if all your dependencies are available for your dev env system arch (which is very unlikely).

@RunWith(AndroidJUnit4.class)
@Config(
    application = TestApplication.class
)
public class ReactModuleSpec {

    private ReactModule reactModule;

    @Before
    public void beforeEach() {
        // Retrieve application context.
        Context applicationContext = ApplicationProvider.getApplicationContext();

        // Recreate ReactApplicationContext which ReactModule depends upon.
        // ReactApplicationContext sole purpose as documented in its source code
        // is to preserve type integrity of ApplicationContext over Context
        // (which android Context obviously does not). This should be safe
        // thus. See my post here:
        // `https://mcmap.net/q/1373660/-writing-unit-test-for-react-native-native-android-methods`.
        ReactApplicationContext reactApplicationContext = new ReactApplicationContext(applicationContext);

        // Instantiate the module.
        reactModule = new ReactModule(reactApplicationContext);
    }

    // ...

}
public class TestApplication extends Application implements ReactApplication {

    // ...

    // Remove packages incompatible with Robolectric.
    @Override
    protected List<ReactPackage> getPackages() {
        List<ReactPackage> packages = new PackageList(this).getPackages();

        // ... Your standard stuffs

        packages.removeIf(pkg -> pkg.getClass().isInstance(BugsnagReactNative.getPackage().getClass()));

        return packages;
    }

    // Remove soloader !
    @Override
    public void onCreate() {
        super.onCreate();

        // Bye bye!
        // BugsnagReactNative.start(this);
        // SoLoader.init(this, /* native exopackage */ false);
    }
}
Salientian answered 9/11, 2019 at 21:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.