我一直试图模仿
clazz = Class.forName("Complete Class path")
Object obj = clazz.Constructor().getInstance();
我用Google搜索,并找到了如何使用powermock模拟静态方法的链接。我尝试使用这些逻辑来模拟
Class.forName("Complete Class path")
和
Object obj = clazz.Constructor().getInstance()
但一直面临错误。
at sun.reflect.GeneratedSerializationConstructorAccessor16.newInstance(Unknown Source) [junit]
at java.lang.reflect.Constructor.newInstance(Constructor.java:423) [junit]
at org.objenesis.instantiator.sun.SunReflectionFactoryInstantiator.newInstance(SunReflectionFactoryInstantiator.java:45) [junit]
at org.powermock.reflect.internal.WhiteboxImpl.newInstance(WhiteboxImpl.java:223) [junit]
at org.powermock.reflect.Whitebox.newInstance(Whitebox.java:139) [junit]
at org.powermock.api.mockito.internal.mockcreation.MockCreator.mock(MockCreator.java:64) [junit]
at org.powermock.api.mockito.PowerMockito.mock(PowerMockito.java:203) [junit]
at org.powermock.api.extension.listener.AnnotationEnabler.standardInject(AnnotationEnabler.java:106) [junit]
at org.powermock.api.extension.listener.AnnotationEnabler.beforeTestMethod(AnnotationEnabler.java:54) [junit]
at org.powermock.tests.utils.impl.PowerMockTestNotifierImpl.notifyBeforeTestMethod(PowerMockTestNotifierImpl.java:90) [junit]
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.executeTest(PowerMockJUnit44RunnerDelegateImpl.java:292) [junit]
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTestInSuper(PowerMockJUnit47RunnerDelegateImpl.java:127) [junit]
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTest(PowerMockJUnit47RunnerDelegateImpl.java:82) [junit]
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runBeforesThenTestThenAfters(PowerMockJUnit44RunnerDelegateImpl.java:282) [junit]
at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:87) [junit]
at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:50) [junit]
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.invokeTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:207) [junit]
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.runMethods(PowerMockJUnit44RunnerDelegateImpl.java:146) [junit]
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$1.run(PowerMockJUnit44RunnerDelegateImpl.java:120) [junit]
at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:34) [junit]
at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:44) [junit]
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.run(PowerMockJUnit44RunnerDelegateImpl.java:122) [junit]
at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:106) [junit]
at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:53)
答案 0 :(得分:2)
我不相信嘲笑Class
是一个好主意,你应该重写你的代码以使其更易于测试。您应该将组件创建委托给工厂,然后很容易模拟它。
以下是您的工厂的样子:
public interface MyObjectFactory {
MyObject create();
}
然后,在您需要创建此对象的类中,将工厂添加为字段
public class MyClass {
// The factory that will create my objects
private MyObjectFactory factory;
public void someMethod() {
// Calls the factory to create my object
MyObject object = factory.create();
...
}
}
完成后,您可以使用Mockito模拟MyObjectFactory
,以便提供您选择的MyObject
个实例。
测试案例将是:
@RunWith(MockitoJUnitRunner.class)
public class MyClassTest {
@Mock
MyObjectFactory factory;
@InjectMocks
MyClass myClass = new MyClass();
@Test
public void testSomeMethod() {
...
Mockito.when(factory.create()).thenReturn(myObject);
// Call the method
myClass.someMethod();
}
}
答案 1 :(得分:1)
由于早期forName
加载这一事实,我认为你无法通过模拟静态Class
方法取得成功。我不知道可以做到这一点的模拟框架。
但是,如果您正在测试自己的代码,那么我建议您将Class.forName
逻辑移到此strategy
interface ClassLoadingStrategy {
ClassLoadingStrategy DEFAULT = Class::forName;
Class<?> forName(final String name) throws Exception;
}
重写您的代码,以便在需要Class.forName
的地方使用它,并在测试中将其替换为mock。