简体   繁体   中英

Can I unit test a class that uses java.lang.reflect.Constructor? (Invalid length in LocalVariableTable)

I'm trying to unit test some old legacy code. I've been using Mockito, PowerMockito, and Whitebox to test private and static methods. I've tested several large and hairy classes successfully, but I've run into a problem with one particular class. I think it has to do with a class that this class extends. The parent class (AjaxEnabledModule) uses java.lang.reflect.Constructor like this:

public AjaxEnabledForm getForm(AjaxEnabledFormType formType) {
 if (!this.forms.containsKey(formType)) {
  Class<?>[] classesParameter = new Class<?>[] { AjaxEnabledModule.class };
  Object[] valuesParameter = new Object[] { this };
  Class<? extends AjaxEnabledForm> clazz = formType.getFormClass();
  try {
    Constructor<? extends AjaxEnabledForm> constructor = clazz.getConstructor(classesParameter);
    setForm(constructor.newInstance(valuesParameter));
  }
  catch (NoSuchMethodException e) {
    Logger.getLogger(getClass()).error("Invalid constructor for: " + clazz.getCanonicalName());
  }
  catch (IllegalArgumentException e) {
    Logger.getLogger(getClass()).error(
        "Invalid argument(s): " + classesParameter + " for Constructor: " + clazz.getCanonicalName());
  }
  catch (InstantiationException e) {
    Logger.getLogger(getClass()).error("Unable to instantiate new Form: " + clazz.getCanonicalName());
  }
  catch (IllegalAccessException e) {
    Logger.getLogger(getClass()).error("Constructor for: " + clazz.getCanonicalName() + " is not accessable");
  }
  catch (InvocationTargetException e) {
    Logger.getLogger(getClass()).error("Invalid Invocation Target for Constructor: " + clazz.getCanonicalName());
  }
}
return this.forms.get(formType);
}

I'm just guessing that this is the problem because not much else is going on in the parent class. I'm not trying to test the functionality of the parent class directly, but I can't test anything in the child class. I can't get any tests to run that use @RunWith(PowerMockRunner.class) and am getting this error:

java.lang.ClassFormatError: Invalid length 3526 in LocalVariableTable in class file resultsreview/base/AjaxEnabledModule
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClassCond(ClassLoader.java:630)
at java.lang.ClassLoader.defineClass(ClassLoader.java:614)
at java.lang.ClassLoader.defineClass(ClassLoader.java:464)
at org.powermock.core.classloader.MockClassLoader.loadMockClass(MockClassLoader.java:268)
at org.powermock.core.classloader.MockClassLoader.loadModifiedClass(MockClassLoader.java:179)
at org.powermock.core.classloader.DeferSupportingClassLoader.loadClass(DeferSupportingClassLoader.java:70)
at java.lang.ClassLoader.loadClass(ClassLoader.java:246)
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClassCond(ClassLoader.java:630)
at java.lang.ClassLoader.defineClass(ClassLoader.java:614)
at java.lang.ClassLoader.defineClass(ClassLoader.java:464)
at org.powermock.core.classloader.MockClassLoader.loadMockClass(MockClassLoader.java:268)
at org.powermock.core.classloader.MockClassLoader.loadModifiedClass(MockClassLoader.java:179)
at org.powermock.core.classloader.DeferSupportingClassLoader.loadClass(DeferSupportingClassLoader.java:70)
at java.lang.ClassLoader.loadClass(ClassLoader.java:246)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:247)
at sun.reflect.generics.factory.CoreReflectionFactory.makeNamedType(CoreReflectionFactory.java:95)
at sun.reflect.generics.visitor.Reifier.visitClassTypeSignature(Reifier.java:107)
at sun.reflect.generics.tree.ClassTypeSignature.accept(ClassTypeSignature.java:31)
at sun.reflect.annotation.AnnotationParser.parseSig(AnnotationParser.java:370)
at sun.reflect.annotation.AnnotationParser.parseClassValue(AnnotationParser.java:351)
at sun.reflect.annotation.AnnotationParser.parseClassArray(AnnotationParser.java:653)
at sun.reflect.annotation.AnnotationParser.parseArray(AnnotationParser.java:460)
at sun.reflect.annotation.AnnotationParser.parseMemberValue(AnnotationParser.java:286)
at sun.reflect.annotation.AnnotationParser.parseAnnotation(AnnotationParser.java:222)
at sun.reflect.annotation.AnnotationParser.parseAnnotations2(AnnotationParser.java:69)
at sun.reflect.annotation.AnnotationParser.parseAnnotations(AnnotationParser.java:52)
at java.lang.Class.initAnnotationsIfNecessary(Class.java:3070)
at java.lang.Class.getAnnotation(Class.java:3029)
at org.junit.internal.MethodSorter.getDeclaredMethods(MethodSorter.java:52)
at org.junit.internal.runners.TestClass.getAnnotatedMethods(TestClass.java:45)
at org.junit.internal.runners.MethodValidator.validateTestMethods(MethodValidator.java:71)
at org.junit.internal.runners.MethodValidator.validateStaticMethods(MethodValidator.java:44)
at org.junit.internal.runners.MethodValidator.validateMethodsForDefaultRunner(MethodValidator.java:50)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.validate(PowerMockJUnit44RunnerDelegateImpl.java:108)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.<init>(PowerMockJUnit44RunnerDelegateImpl.java:70)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.createDelegatorFromClassloader(JUnit4TestSuiteChunkerImpl.java:156)
at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.createDelegatorFromClassloader(JUnit4TestSuiteChunkerImpl.java:40)
at org.powermock.tests.utils.impl.AbstractTestSuiteChunkerImpl.createTestDelegators(AbstractTestSuiteChunkerImpl.java:244)
at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.<init>(JUnit4TestSuiteChunkerImpl.java:61)
at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.<init>(AbstractCommonPowerMockRunner.java:32)
at org.powermock.modules.junit4.PowerMockRunner.<init>(PowerMockRunner.java:34)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
at org.junit.internal.builders.AnnotatedBuilder.buildRunner(AnnotatedBuilder.java:29)
at org.junit.internal.builders.AnnotatedBuilder.runnerForClass(AnnotatedBuilder.java:21)
at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:26)
at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
at org.junit.internal.requests.ClassRequest.getRunner(ClassRequest.java:26)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.<init>(JUnit4TestReference.java:33)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestClassReference.<init>(JUnit4TestClassReference.java:25)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.createTest(JUnit4TestLoader.java:48)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.loadTests(JUnit4TestLoader.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:452)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

I've seen other posts that receive an error like this when using an old version of javassist. I was using javassist-20 but removed it and I'm still getting this error. I'd really love to keep using PowerMockito since it is what I'm familiar with. Does anyone know how to either fix this error or know of another framework that doesn't use PowerMockRunner that can mock private and static methods?

Versions: -Java 6 - PowerMock jars version 1.6.3
- Mockito version 1.10.19.

(I was using Javassist-20 but removed it completely and am still getting the error.)

I should also say that this is not a Maven project, unfortunately. I'm using Eclipse and I don't see any reference to javassist in the build path or doing a file search.

I thought I'd come back and update this question. I've found that I cannot use PowerMockito to test a class that uses reflection (or inherits from a class that uses reflection). I don't think there's any way around it other than to re-factor the parent class to not use reflection if I want to unit test.

Another update: Once we converted our old project into a Maven project, I was able to successfully test this class. I don't know why, but I no longer get the error above in the Maven project.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM