Prueba de unidad clase Java que carga biblioteca nativa



2 Answers

No estoy seguro de si esto resuelve su problema o no, pero hasta ahora nadie ha mencionado el patrón de estrategia para tratar con las clases que precargan la biblioteca durante su creación.

Veamos el ejemplo:

Queremos implementar la clase de solucionador de Fibonacci. Suponiendo que proporcionamos la implementación en el código nativo y logramos generar la biblioteca nativa, podemos implementar lo siguiente:

public interface Fibonacci {
     long calculate(int steps);
}

En primer lugar, ofrecemos nuestra implementación nativa:

public final class FibonacciNative implements Fibonacci {
    static {
      System.loadLibrary("myfibonacci");
    }

    public native long calculate(int steps);
}

En segundo lugar, proporcionamos la implementación de Java para el solucionador de Fibonacci:

public final class FibonacciJava implements Fibonacci {

   @Override
   public long calculate(int steps) {
       if(steps > 1) {
           return calculate(steps-2) + calculate(steps-1);
       }
       return steps;
   }
}

En tercer lugar, ajustamos los solucionadores con la clase parental eligiendo su propia implementación durante la creación de instancias:

public class FibonnaciSolver implements Fibonacci {

   private static final Fibonacci STRATEGY;

   static {
      Fibonacci implementation;
      try {
         implementation = new FibonnaciNative();
      } catch(Throwable e) {
         implementation = new FibonnaciJava();
      }

      STRATEGY = implementation;
   }

   @Override
   public long calculate(int steps) {
       return STRATEGY.calculate(steps);
   }

}

Por lo tanto, el problema de encontrar el camino a la biblioteca usando la estrategia. Este caso, sin embargo, no resuelve el problema si la biblioteca nativa es realmente necesaria para ser incluida durante la prueba. Tampoco resuelve el problema si la biblioteca nativa es una biblioteca de terceros.

Básicamente, esto evita el problema de carga de la biblioteca nativa burlándose del código nativo para el código de Java.

Espero que esto ayude de alguna manera :)

Question

Estoy ejecutando pruebas unitarias en Android Studio. Tengo una clase de Java que carga una biblioteca nativa con el siguiente código

 static
    {
       System.loadLibrary("mylibrary");
    }

Pero cuando pruebo esta clase dentro de mi directorio src/test obtengo

java.lang.UnsatisfiedLinkError: no mylibrary in java.library.path
    at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1864)
    at java.lang.Runtime.loadLibrary0(Runtime.java:870)
    at java.lang.System.loadLibrary(System.java:1122)

¿Cómo puedo hacer que encuentre la ruta de las librerías nativas .so que se encuentra en src/main/libs para poder realizar pruebas unitarias sin errores?

Nota: dentro del directorio src/main/libs tengo 3 subdirectorios más: armeabi , mips y x86 . Cada uno de ellos contiene el archivo .so adecuado. Estoy usando la versión no experimental para construir librerías NDK.

No quiero usar otras bibliotecas de prueba de terceros, ya que todas mis otras clases de Java "puras" pueden ser probadas en una sola unidad. Pero si eso no es posible, entonces estoy abierto a otras alternativas.

Aquí está mi código de prueba que arroja el error

   @Test
    public void testNativeClass() throws Exception
    {
        MyNativeJavaClass test = new MyNativeJavaClass("lalalal")
        List<String> results = test.getResultsFromNativeMethodAndPutThemInArrayList();
        assertEquals("There should be only three result", 3, results.size());
    }



Solo asegúrese de que el directorio que contiene la biblioteca se encuentre en la propiedad del sistema java.library.path .

De la prueba, puede configurarlo antes de cargar la biblioteca:

System.setProperty("java.library.path", "... path to the library .../libs/x86");

Puede especificar la ruta codificada, pero esto hará que el proyecto sea menos portátil para otros entornos. Entonces sugiero que lo desarrolles programáticamente.




Intente ejecutar el código de prueba con la opción java -XshowSettings: properties y asegúrese de que su ruta de destino para las bibliotecas del sistema y en el resultado de este comando, los valores de ruta de la biblioteca sean los mismos




Related