ClassNotFoundException 当 运行 从 jar 中设置 class 但如果我直接在我的应用程序中 运行 class 它工作

ClassNotFoundException when running a class from a jar but if I run the class directly in my application it works

我想在我们的 application 中添加一个部分,允许用户上传包含 JUnit 测试的 jar。我希望能够在我的 java application 中 运行 这些 jar 的测试。我可以让 ClassJar 加载,但是当它转到 运行 时,测试将失败,并显示所需库的错误 ClassNotFoundException。如果我在我的应用程序中放置相同的 Class 和 运行 它,它工作正常。我正在通过 maven 加载所有库。

当运行宁:

Result result = junit.run(c.getClass());
                for (Failure failure : result.getFailures()) {
                    Logger.info("Failure: " + failure.toString());
                }

输出:(详细堆栈跟踪见下文)

java.lang.ClassNotFoundException: org.openqa.selenium.Capabilities

问题

如果我 运行 将 Test class 放在 classpath 中并通过 class 直接调用它,它可以正常工作并且运行s Appium

内的测试
JUnitCore junit = new JUnitCore();
Result result = junit.run(Test.class);

当我从 jar 加载相同的 class 时,它失败了。

问题

有人知道为什么会这样吗?

当 运行 加载 `jar 时,它会使用应用程序加载的库,还是我需要将所需的库打包到 class 路径加载器上的 jar/directly 中?

Maven 已设置为正确导入所有 Selenium/Appium jar。如果我 运行 直接在我的应用程序中进行测试,那么当 class 从罐子中取出时就没有问题。

 import org.openqa.selenium.remote.DesiredCapabilities; 

我应该直接在 classloader 上添加 Selenium/Appium jar 吗?

URL[] classLoaderUrls = new URL[]{new URL("file:///c:/Work 2016/simpleappiumtest2.jar"), new URL("file:///c:/Work 2016/libraries/Selenium/selenium-server-standalone-2.53.0.jar")};

当我这样做时,我无法将其发送到 运行。

在这里更新是我可以 运行 代码的另一种方式,它也失败了。

        try {
        // Getting the jar URL which contains target class
        URL[] classLoaderUrls = new URL[]{new URL("file:///c:/Work 2016/simpleappiumtest2.jar")};
        //Code to run junit test
        URLClassLoader urlClassLoader = new URLClassLoader(classLoaderUrls);
         // Load the target class
        Class<?> appiumClass = urlClassLoader.loadClass("simpleapp.simpleappium");
        // Run the class using JUnitCore
        JUnitCore junit = new JUnitCore();
        Result result = junit.run(appiumClass);
        //Display if test was successful
        Logger.info(result.wasSuccessful());

        Logger.info("Tests run: " + result.getRunCount());
        Logger.info("Tests failed: " + result.getFailureCount());
        for (Failure failure : result.getFailures()) {
            Logger.info("Failure: " + failure.toString());
            Logger.info("Failure desc: " + failure.getDescription());
            Logger.info("Failure excp: " + failure.getException());
            Logger.info("Failure trace: " + failure.getTrace());
        }
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

代码

   // not on class path File jarLocation = new File("C:/Work/testcases-0.0.1.jar");
   File jarLocation = new File("lib/testcases-0.0.1.jar");  // on classpath

    try {

        JarInputStream testJarFile;
        testJarFile = new JarInputStream(new FileInputStream(jarLocation));

        while (true) {
            JarEntry testJar = testJarFile.getNextJarEntry();
            if (testJar == null) {
              break;
            }
            if ((testJar.getName().endsWith(".class"))) {

                String file = testJar.getName();
                String classname = file.replace('/', '.').substring(0, file.length() - 6);
                try 
                {
                    Class<?> c = Class.forName(classname);


                    JUnitCore junit = new JUnitCore();
                    Result result = junit.run(c.getClass());
                    for (Failure failure : result.getFailures()) {

                Logger.info("Failure: " + failure.toString());
                Logger.info("Failure desc: " + failure.getDescription());
                Logger.info("Failure excp: " + failure.getException());
                Logger.info("Failure trace: " + failure.getTrace());
                    }

                }
                catch (Throwable e) 
                {
                    Logger.error("WARNING: failed to instantiate " + classname + " from " + file);
                    Logger.error("ERROR: Exception " + e);
                }
            }
        }
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

测试Class

  public class Test {

      @Test
      public void test() throws MalformedURLException {

          //Grab file - device info
          File appDir = new File("lib");
          File app = new File(appDir, "deviceinfo.apk");

          //Setup as android device
          DesiredCapabilities cap = new DesiredCapabilities();
          cap.setCapability(MobileCapabilityType.PLATFORM_NAME, MobilePlatform.ANDROID);
          cap.setCapability(MobileCapabilityType.DEVICE_NAME, "Android Device");

          //Run app
          cap.setCapability(MobileCapabilityType.NEW_COMMAND_TIMEOUT, "20");  //only wait 20 sec
          cap.setCapability(MobileCapabilityType.APP, app.getAbsolutePath());
          AndroidDriver driver = new AndroidDriver(new URL("http://127.0.0.1:4723/wd/hub"), cap);

          //Close app
          driver.closeApp();
      }
  }

堆栈跟踪

2016-05-26 09:11:49 [http-nio-8082-exec-1] INFO  com.miw.mcb.server.MCBLogger - ::::: MCBLogger ::::: Failure: initializationError(com.miw.mcb.testcases.AndroidTest): org/openqa/selenium/Capabilities
2016-05-26 09:11:49 [http-nio-8082-exec-1] INFO  com.miw.mcb.server.MCBLogger - ::::: MCBLogger ::::: Failure desc: initializationError(com.miw.mcb.testcases.AndroidTest)
2016-05-26 09:11:49 [http-nio-8082-exec-1] INFO  com.miw.mcb.server.MCBLogger - ::::: MCBLogger ::::: Failure excp: java.lang.NoClassDefFoundError: org/openqa/selenium/Capabilities
2016-05-26 09:11:49 [http-nio-8082-exec-1] INFO  com.miw.mcb.server.MCBLogger - ::::: MCBLogger ::::: Failure trace: java.lang.NoClassDefFoundError: org/openqa/selenium/Capabilities
        at java.lang.Class.getDeclaredMethods0(Native Method)
        at java.lang.Class.privateGetDeclaredMethods(Class.java:2701)
        at java.lang.Class.privateGetMethodRecursive(Class.java:3048)
        at java.lang.Class.getMethod0(Class.java:3018)
        at java.lang.Class.getMethod(Class.java:1784)
        at org.junit.internal.builders.SuiteMethodBuilder.hasSuiteMethod(SuiteMethodBuilder.java:18)
        at org.junit.internal.builders.SuiteMethodBuilder.runnerForClass(SuiteMethodBuilder.java:10)
        at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
        at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:26)
        at org.junit.runner.Computer.getRunner(Computer.java:40)
        at org.junit.runner.Computer.runnerForClass(Computer.java:31)
        at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
        at org.junit.runners.model.RunnerBuilder.runners(RunnerBuilder.java:101)
        at org.junit.runners.model.RunnerBuilder.runners(RunnerBuilder.java:87)
        at org.junit.runners.Suite.<init>(Suite.java:81)
        at org.junit.runner.Computer.getSuite(Computer.java:28)
        at org.junit.runner.Request.classes(Request.java:75)
        at org.junit.runner.JUnitCore.run(JUnitCore.java:105)
        at org.junit.runner.JUnitCore.run(JUnitCore.java:94)
        at com.miw.mcb.adbservice.controller.HomeController.runAppiumTest(HomeController.java:511)
        at com.miw.mcb.adbservice.controller.HomeController.runTestRunOnDevice(HomeController.java:268)
        at com.miw.mcb.adbservice.controller.HomeController.runTest(HomeController.java:162)
        at com.miw.mcb.adbservice.controller.HomeController.runTestRun(HomeController.java:128)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221)
        at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136)
        at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110)
        at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:817)
        at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:731)
        at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
        at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
        at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
        at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:968)
        at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:870)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:707)
        at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:844)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:292)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
        at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
        at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
        at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:87)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
        at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
        at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:121)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:522)
        at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1095)
        at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:672)
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1500)
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1456)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
        at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.ClassNotFoundException: org.openqa.selenium.Capabilities
        at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
        at java.net.FactoryURLClassLoader.loadClass(URLClassLoader.java:814)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
        ... 76 more

POM

<dependency>
  <groupId>junit</groupId>
  <artifactId>junit</artifactId>
  <version>4.12</version>
</dependency>

<!-- add appium dependencies -->
<dependency>
  <groupId>io.appium</groupId>
  <artifactId>java-client</artifactId>
  <version>3.4.1</version>
</dependency>

<dependency>
  <groupId>org.zeroturnaround</groupId>
  <artifactId>zt-process-killer</artifactId>
  <version>1.4</version>
</dependency>

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.2</version>
</dependency>

<dependency>
    <groupId>org.codehaus.plexus</groupId>
    <artifactId>plexus-utils</artifactId>
    <version>3.0.24</version>
</dependency>

<dependency>
  <groupId>org.seleniumhq.selenium</groupId>
  <artifactId>selenium-server</artifactId>
  <version>2.53.0</version>
</dependency>

<dependency>
    <groupId>org.seleniumhq.selenium</groupId>
    <artifactId>selenium-remote-driver</artifactId>
    <version>2.53.0</version>
</dependency>

<dependency>
    <groupId>org.seleniumhq.selenium</groupId>
    <artifactId>selenium-android-driver</artifactId>
    <version>2.39.0</version>
</dependency>

需要加载当前类路径以允许访问应用程序加载的库

URLClassLoader cl = new URLClassLoader(classLoaderUrls, getClass().getClassLoader());