JUnit & Powermock: Native Library already loaded in another classloader

不羁岁月 提交于 2020-01-04 05:14:10

问题


I have some test classes that need to verify that GLFW-functions were called. But when I want to execute all tests in IntelliJ then I get the error:

Native Library lwjgl.dll already loaded in another classloader

I use Powermock to verify that the static methods have been called:

@RunWith(PowerMockRunner.class)
@PrepareForTest({GLFW.class})
public class GlfwWindowImplTest {
    // ...
    @Test
    public void update_swapsBufferAndPollsEvents() {
        GlfwWindowImpl target = new GlfwWindowImpl(1L);
        mockStatic(GLFW.class);

        target.update();

        verifyStatic();
        GLFW.glfwSwapBuffers(1L);
        verifyStatic();
        GLFW.glfwPollEvents();
    }
}

@RunWith(PowerMockRunner.class)
@PrepareForTest({GLFW.class})
public class GlfwWindowSystemImplTest {
    // ...
    @Test(expected = GlfwInitializeException.class)
    public void initialize_throwsExceptionIfGlfwInitFails() {
        GlfwWindowSystemImpl target = new GlfwWindowSystemImpl();
        mockStatic(GLFW.class);
        when(GLFW.glfwInit()).thenReturn(GL_FALSE);

        target.initialize();
    }
}

回答1:


It may be a bit late to answer this post, but I ran into a similar problem and I was able to solve it with PowerMock. PowerMock has @SuppressStaticInitializationFor that should help you overcome this issue. Section Suppress static initializer in the link below has a nice example about how to do that:

https://github.com/powermock/powermock/wiki/Suppress-Unwanted-Behavior

Basically, in your case, there could be a class that is calling System.loadLibrary("lwjgl"). You need to locate that class. Example:

public class SomeClass {
    ...
    static {
        System.loadLibrary ("lwjgl");
    }
    ...
}

Then in your test class use @SuppressStaticInitializationFor with the fully qualified name of the class:

@SuppressStaticInitializationFor("com.example.SomeClass")

If in case the class doing the loadLibrary call is an inner class, then you need to add $InnerClass to fully qualify the inner class. Example:

public class SomeClass {
    ...
    public static class SomeInnerClass {
        static {
            System.loadLibrary ("lwjgl");
        }
    }
    ...
}

Then you need to use:

@SuppressStaticInitializationFor("com.example.SomeClass$SomeInnerClass")



回答2:


@PrepareForTest({GLFW.class}) loads the ClassLoader for the native library lwjgl.dll which is already loaded in the ClassLoader.

You can use the @PowerMockIgnore to defer the loading of classes with the names supplied to value() to the system ClassLoader.

For example suppose you'd like to defer the loading of all classes in the org.myproject package and all its sub-packages but you still like to prepare "MyClass" for test. Then you do like this:


 @PowerMockIgnore("org.myproject.*")
 @PrepareForTest(MyClass.class)
 @RunWith(PowerMockRunner.class)
 public class MyTest {
 ...
 }

JavaDoc Reference




回答3:


@PrepareForTest({GLFW.class}) create new ClassLoader and load ammended class in it. I suspect that GLFW load lwjgl library in its static initializer section.

You can try to unload library, but I don't know what consequences it may lead to.

I suggest wrap GLFW and use that wrapper in your applicatin.



来源:https://stackoverflow.com/questions/39248363/junit-powermock-native-library-already-loaded-in-another-classloader

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!