2012-03-09 2 views
1

동적으로 외부 클래스 '테스트를 실행하는 메소드를 작성하려고합니다. JDK 라이브러리 만 사용하는 테스트를 실행할 수 있지만 org.jmock.Mockery와 같은 다른 라이브러리를 사용하는 테스트를 실행하면 JUnitCore.run (args)에 의해 반환 된 Result 객체에 다음 오류가 발생합니다.JUnitCore가 테스트 케이스에 필요한 라이브러리를로드하지 않았습니다.

[initializationError(package.TestClass): org/jmock/Mockery] 
java.lang.NoClassDefFoundError: org/jmock/Mockery 

com.sun.jdi.ClassNotLoadedException: Type has not been loaded occurred while retrieving component type of array. 

물론 이클립스에서 원래 프로젝트에서 테스트를 실행하면 통과 할 수 있습니다.

ClassLoader는 테스트중인 클래스를로드하고 외부 프로젝트의 클래스 경로에 정의 된 종속성 (예 : jars)을로드하지 않기 때문에이 문제는 클래스 경로와 관련이 있다고 생각합니다. 실행중인 응용 프로그램에 jar를 동적으로로드하는 방법을 모르겠습니다.

다음은 클래스를로드하고 테스트를 실행하는 코드입니다. 사전에

URL url = new File("E:\eclipseProjectName\bin\").toURL(); 
final URL[] urls = new URL[] { url }; 
final ClassLoader cl = new URLClassLoader(urls); 
@SuppressWarnings("rawtypes") 
final Class cls = cl.loadClass("package.ClassName"); 
final JUnitCore core = new JUnitCore(); 
final Result result = new JUnitCore().run(Request.method(cls, "methodName")); 

감사합니다,

마크 CACHIA

+0

테스트를 어떻게 실행합니까? 이클립스, 개미, 다른 거? 테스트 러너 내에서 클래스 패스를 어떻게 설정하고 있습니까? – unholysampler

+0

위의 코드를 사용하여 프로그래밍 방식으로 테스트가 실행됩니다. 실행을 시작한 후에 classpath에 jar를 동적으로 추가하는 방법을 모르겠다. 이것이 문제라고 생각한다. 나는 많은 연구를 해왔고 이렇게하는 것이 불가능한 것처럼 보였지만 IDE는 외부 테스트를 실행했다. – cachiama

+1

어떻게 외부 항아리를로드 할 수 있습니까? – oers

답변

0

I에 의해 당신이 무슨 뜻인지 잘 모르겠어요 : 당신은 당신이 가지고 자바의 클래스에 대한 액세스를 원하는 경우

I believe the issue is related the classpath as the ClassLoader is seemingly only loading the class being tested and not loading dependencies (like jars) defined in the external project's classpath.

클래스 패스에 놓거나 직접 찾아서로드하십시오. 당신 자신의 클래스 로더를 사용하여 클래스 경로에 Eclipse 프로젝트 bin 경로를 추가하는 것처럼 보이지만 Mockery가 클래스 경로에 추가되지 않습니다. Eclipse bin 경로에는 컴파일 한 클래스 만 들어 있습니다. Mockery jar를 특별히로드해야합니다. java -cp을 사용하여 모든 것을 jvm의 classpath에 놓기 만하면됩니다.

좋아, 문제를 이해하기 시작했습니다. elses 프로젝트에서 테스트 세트를 실행하려고하지만 테스트가 다른 종속성을 참조하면 작동하지 않습니다. 짧은 대답은 : 이것은 어렵다. 당신은 외부 프로젝트의 참조 된 클래스/jar를 기반으로 classLoader에 추가해야하는 클래스를 찾으려고합니다.

여기에는 몇 가지 방법이 있습니다. 외부 프로젝트가 Eclipse로 빌드 된 것이 확실하다면, .project.classpath을보고 외부 프로젝트의 종속성을 찾을 수 있습니다. 다른 컨테이너에 대한 참조를 포함 할 수 있기 때문에 간단하지 않습니다. 이것은 내 프로젝트 중 하나의 .classpath입니다.

<?xml version="1.0" encoding="UTF-8"?> 
<classpath> 
    <classpathentry kind="src" output="target/classes" path="src/main/java"/> 
    <classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources"/> 
    <classpathentry kind="src" output="target/test-classes" path="src/test/java"/> 
    <classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources"/> 
    <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/> 
    <classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/> 
    <classpathentry kind="output" path="target/classes"/> 
</classpath> 

여기에는 Maven 컨테이너와 같은 컨테이너에 대한 참조가 포함되어 있습니다. 이것이 귀하의 프로젝트에서 성취 할 수 있다고 생각한다면, 이것이 이것을 달성하는 한 가지 방법 일 수 있습니다. 훨씬 더 좋은 방법은 받는다는 또는 유사한의 사용을 강제하는 것입니다, 그리고 당신은 당신이 젠킨스에서 & 빌드에게 프로젝트를 실행하면 당신은 좋은거야하는 추가 보너스와 함께 단지

$ mvn test 

하여 테스트를 실행할 수 있습니다 보고서뿐입니다.

+0

답장을 보내 주셔서 감사합니다. 어쩌면 내가 분명하지 않을 수도 있습니다. 이 애플리케이션에서는 외부 테스트를 동적으로로드하고 실행하므로 사용자가 자신의 Java 프로젝트를 가리킬 때까지 어떤 라이브러리가 사용되는지 알지 못합니다. 런타임에 외부 라이브러리를 프로그래밍 방식으로로드 할 수 있습니까? – cachiama

+0

@cachiama : 실제 응용 프로그램이 실행될 때의 경우 일지 모르지만 지금은 테스트에 대해 이야기하고 있습니다. 작성한 테스트는 결정 론적이어야하며 항상 동일한 결과를 산출해야합니다. 따라서 테스트 코드가로드하려고하는 종속성을 알아야합니다. – unholysampler

+0

다시 나는 나 자신을 분명히하지 않았다고 믿는다. 내 응용 프로그램의 목적은 외부 응용 프로그램의 테스트를 동적으로로드하여 실행하고 어떤 테스트가 통과했는지, 어떤 테스트가 통과하지 않았는지를 보여주는 것입니다. 문제는 외부 테스트를 실행하고 외부 라이브러리를 사용하는 경우입니다. 응용 프로그램의 JUnitCore가 ClassNotFound 예외를 내부적으로 포착하고 테스트가 실패합니다. 내 응용 프로그램의 JUnitCore가 참조 된 클래스를로드 할 수 있도록 현재 외부 응용 프로그램에서 사용하는 라이브러리를로드하고 싶습니다. – cachiama

0

당신이 테스트를 실행하는 응용 프로그램에서 사용하는 라이브러리를로드 할 경우 현재의 클래스 로더를로드 설치하여 URLClassLoader하는 것이 좋습니다 다음 클래스에 대한 참조가 당신이

을 테스트하기 위해 노력하고있다
URLClassLoader cl = new URLClassLoader(classLoaderUrls, getClass().getClassLoader()); 

다음은 jar에서 클래스를 동적으로로드하는 예제입니다. 이름으로 한 클래스 만로드하려면 위와 동일하게 할 수 있습니다.

File pathToJar = new File(jarPath); 

    JarFile jarFile; 
    jarFile = new JarFile(pathToJar); 
    Enumeration<JarEntry> e = jarFile.entries(); 

    URL[] classLoaderUrls = new URL[]{pathToJar.toURI().toURL()}; 

    URLClassLoader cl = new URLClassLoader(classLoaderUrls, getClass().getClassLoader()); 
    while (e.hasMoreElements()) { 

     // load all the classes in the jar (or you can set it up to use the exact class/method name as you did above 
     JarEntry je = e.nextElement(); 
     if(je.isDirectory() || !je.getName().endsWith(".class")){ 
      continue; 
     } 
     // -6 because of .class 
     String className = je.getName().substring(0,je.getName().length()-6); 
     className = className.replace('/', '.'); 
     Class c = cl.loadClass(className); 


     JUnitCore junit = new JUnitCore(); 
     Result result = junit.runClasses(c); 
     // check for failed/ passed tests here 

    } 
관련 문제