Search code examples
androidunit-testingkotlinjarmockito

Android Unit test : java.lang.UnsatisfiedLinkError: no <library-name> in java.library.path


I write this message because I am facing an issue with my android unit testing and I need your help please.

Actually in my Android app I am using a module (object) that I import from a jar file :

  • I have a toto.jar in my /project/libs (for example /project/libs/toto.jar)
  • In my build.gradle I have those two lines in order to import the jar file :

api fileTree(dir: "libs", include: ["*.jar"])

implementation fileTree(include: ['*.so'], dir: 'jniLibs')

  • in my MainActivityHelper I import the class of the library toto :
import com.toto.library.myClass

Then I use it like this in a method

 var myClass: MyClass = MyClass()
 myClass.doSomething()

in my unit test file I am trying to mock it :

@Mock
private var mockMyClass: myClass? = null

While trying to run my test , I always got this error :

java.lang.UnsatisfiedLinkError: no <library-name> in java.library.path

I can see that there is a file inside the library that is trying to load a library , and maybe it produced this error message

static {
    try {
        System.loadLibrary("toto");
    } catch (NoClassDefFoundError var1) {
    }

}

But even after searching on many other thread, and tried other solution I don't understand how to make my jar file available for my unit test.

Actually my unit test files are in : /home/username/AndroidStudioProject/project-name/src/test/java/com/my/package

My jar files are in : /home/username/AndroidStudioProject/project-name/libs

Some other ".so" (for example tata.so file), linked to jar files (toto.jar), are in : /home/username/AndroidStudioProject/project-name/src/main/jniLibs

And my app project files are in : /home/username/AndroidStudioProject/project-name/src/main/java

Please is there any way to make it know while unit testing compile , that jar libraries files are in libs folder ? Do I have anything to modify in build.gradle ? (like testOptions ?)

Thank you in advance for your Help !


Solution

  • Finally I found the solution and I share it to you :

    1. In order that test works like on a real device you have to test with instrumented test (Android Runner)

    2. You have to put all your test files inside androidTest directory or your instrumentation test won't work

    /home/username/AndroidStudioProject/project-name/src/androidTest
    
    1. add dependencies, please check if you have to update version number
    androidTestImplementation 'junit:junit:4.13.1'
    androidTestImplementation 'androidx.test:core:1.3.0'
    androidTestImplementation 'org.mockito:mockito-core:3.6.0'
    androidTestImplementation 'androidx.test:runner:1.3.0'
    androidTestImplementation 'androidx.test:rules:1.3.0'
    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
    androidTestImplementation 'org.mockito:mockito-android:3.6.0'
    
    1. add above you test class name declaration :
    @RunWith(AndroidJUnit4::class)
    
    1. in particular cases : If you want to mock an object (class) that you import from an external .jar library and you have external .so file for that library, maybe you will have to check if you have different .so file for different architecture ==>

    For example you have some .so files in your jniLIbs folder /src/main/jniLibs/armeabi-v7a/.so Maybe for your main app armeabi-v7a will be enough, but for intrumented unit test unit you will need other architecture, so just add all folder and .so files gave by the library provider : in plus of armeabi-v7a you will have also :those folder armeabi, x86, x86_64, etc.

    Then your test will pass