【问题标题】:UnsatisfiedLinkError when unit testing WritableNativeMap单元测试 WritableNativeMap 时出现 UnsatisfiedLinkError
【发布时间】:2016-02-08 17:33:04
【问题描述】:

我目前正在创建一个 Android 库以用于 React Native 项目。我需要向 javascript 发出地图,所以我使用的是 react native 的 WriteableMap 类。不幸的是,该类将 reactnativejni SO 加载到静态块中,这会在单元测试期间导致 UnsatisfiedLinkError。我正在使用 JUnit 和 Mockito 进行测试。

我的代码:

@Override
public void onSomething() {
    WritableMap params = Arguments.createMap();

    //fill map

    sendEvent("onChange", params);
}

错误:

java.lang.UnsatisfiedLinkError: no reactnativejni in java.library.path
  at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1857)
  at java.lang.Runtime.loadLibrary0(Runtime.java:870)
  at java.lang.System.loadLibrary(System.java:1119)
  at com.facebook.soloader.SoLoader.loadLibrary(SoLoader.java:172)
  at com.facebook.react.bridge.NativeMap.<clinit>(NativeMap.java:23)
  at com.facebook.react.bridge.Arguments.createMap(Arguments.java:29)
  at me.MyClass.onSomething(myClass.java:23)

在看到有关为单元测试存根 WriteableMap 的评论后,我开始使用 Arguments.createMap() 方法,但它是静态的,我宁愿不必存根静态方法。

在运行单元测试时有什么方法可以消除这个错误吗?

【问题讨论】:

    标签: android junit mockito react-native unsatisfiedlinkerror


    【解决方案1】:

    我认为您无法避免在单元测试中模拟 Arguments 方法(尽管我相信您不需要在仪器测试中这样做)。

    在 Facebook 自己的测试中,他们使用PowerMockito 来模拟它们: https://github.com/facebook/react-native/blob/master/ReactAndroid/src/test/java/com/facebook/react/RootViewTest.java#L67

    有趣的位:

    PowerMockito.mockStatic(Arguments.class);
    PowerMockito.when(Arguments.createArray()).thenAnswer(new Answer<Object>() {
      @Override
      public Object answer(InvocationOnMock invocation) throws Throwable {
        return new JavaOnlyArray();
      }
    });
    PowerMockito.when(Arguments.createMap()).thenAnswer(new Answer<Object>() {
      @Override
      public Object answer(InvocationOnMock invocation) throws Throwable {
        return new JavaOnlyMap();
      }
    });
    

    另请注意,这需要您修改 build.gradle 以包含这些模拟工具: https://github.com/facebook/react-native/blob/master/ReactAndroid/build.gradle#L266

    dependencies {
      ...
      testCompile "org.powermock:powermock-api-mockito:${POWERMOCK_VERSION}"
      testCompile "org.powermock:powermock-module-junit4-rule:${POWERMOCK_VERSION}"
      testCompile "org.powermock:powermock-classloading-xstream:${POWERMOCK_VERSION}"
      testCompile "org.mockito:mockito-core:${MOCKITO_CORE_VERSION}"
      testCompile "org.easytesting:fest-assert-core:${FEST_ASSERT_CORE_VERSION}"
      testCompile "org.robolectric:robolectric:${ROBOLECTRIC_VERSION}"
      ...
    }
    

    他们使用的版本可以在他们的gradle.properties 文件中找到。

    我不知道这些测试配置从长远来看会有多稳定,但这种配置让我可以在单元测试中使用 ReadableMap/Array 和 WritableMap/Array。

    【讨论】:

    • 想知道我做错了什么。我设置了 PowerMockito 及其所有依赖项以及@Before setUp,但测试仍然失败,因为 java.library.path 中没有 reactnativejni,但这次它在线 PowerMockito.when(Arguments.createArray())
    • 我只是快速浏览了代码,我认为没有 reactnativejni 它根本行不通。 PowerMockito.when(Arguments.createMap()) 最终将调用 ReactBridge.staticInit 调用 SoLoader.loadLibrary("reactnativejni");因此,即使以后可能可以进行模拟,任何它都是无用的,因为设置模拟将在 ReactBridge.staticInit 上失败。
    【解决方案2】:

    你也可以使用JavaOnlyMap,它同时实现了WritableMapReadableMap

    所以无论你需要在哪里使用Arguments.createMap(),只需替换为new JavaOnlyMap()

    参考:https://github.com/facebook/react-native/blob/master/ReactAndroid/src/main/java/com/facebook/react/bridge/JavaOnlyMap.java

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-01-25
      • 1970-01-01
      • 2013-02-09
      • 2015-12-23
      • 1970-01-01
      • 2017-07-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多