我已经两天试图解决这个问题了!事情是这样的:我有一个班级如下:
public class TaskEntity extends Index {
public String title;
public String description;
public UUID posterId;
public Long time;
public String address;
public GeoPoint location;
public static Finder find = new Finder(TaskEntity.class);
//some methods
}
它扩展了这个抽象类:
public abstract class Index implements Indexable {
//some public non static fields
// some methods
public static class Finder {
private final Class type;
private IndexQueryPath queryPath;
public Finder(Class type) {
this.type = type;
T t = IndexUtils.getInstanceIndex(type); // error here!
this.queryPath = t.getIndexPath();
}
public IndexQueryPath getIndexPath() {
IndexType indexTypeAnnotation = this.getClass().getAnnotation(IndexType.class);
if(indexTypeAnnotation == null) {
Logger.error("ElasticSearch : Class " + this.getClass().getCanonicalName() + " no contain @IndexType(name) annotation ");
}
String indexType = indexTypeAnnotation.name();
String indexName = IndexService.INDEX_DEFAULT; // This is not defined, therefore throw a NullPointerException
IndexName indexNameAnnotation = this.getClass().getAnnotation(IndexName.class);
if(indexNameAnnotation != null) {
indexName = indexNameAnnotation.name();
}
return new IndexQueryPath(indexName, indexType);
}
// some methods
}
}
简单地说,我试着在没有任何额外代码的情况下模拟TaskEntity类,如下所示:
public class TaskManagementServiceImplTest {
@Mock
private TaskEntity taskEntity;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
}
@Test
public void emptyTest(){
}
}
吊杆:
java.lang.ExceptionInInitializerError
at com.github.cleverage.elasticsearch.Index.getIndexPath(Index.java:41)
at com.github.cleverage.elasticsearch.Index$Finder.(Index.java:164)
at models.elasticsearch.TaskEntity.(TaskEntity.java:48)
at sun.reflect.GeneratedSerializationConstructorAccessor6.newInstance(Unknown Source)
at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
at org.objenesis.instantiator.sun.SunReflectionFactoryInstantiator.newInstance(SunReflectionFactoryInstantiator.java:45)
at org.objenesis.ObjenesisBase.newInstance(ObjenesisBase.java:73)
at org.mockito.internal.creation.jmock.ClassImposterizer.createProxy(ClassImposterizer.java:128)
at org.mockito.internal.creation.jmock.ClassImposterizer.imposterise(ClassImposterizer.java:63)
at org.powermock.api.mockito.internal.mockcreation.MockCreator.createMethodInvocationControl(MockCreator.java:111)
at org.powermock.api.mockito.internal.mockcreation.MockCreator.mock(MockCreator.java:60)
at org.powermock.api.mockito.PowerMockito.mock(PowerMockito.java:143)
at org.powermock.api.extension.listener.AnnotationEnabler.standardInject(AnnotationEnabler.java:84)
at org.powermock.api.extension.listener.AnnotationEnabler.beforeTestMethod(AnnotationEnabler.java:51)
at org.powermock.tests.utils.impl.PowerMockTestNotifierImpl.notifyBeforeTestMethod(PowerMockTestNotifierImpl.java:90)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.executeTest(PowerMockJUnit44RunnerDelegateImpl.java:292)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTestInSuper(PowerMockJUnit47RunnerDelegateImpl.java:127)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTest(PowerMockJUnit47RunnerDelegateImpl.java:82)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runBeforesThenTestThenAfters(PowerMockJUnit44RunnerDelegateImpl.java:282)
at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:86)
at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:49)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.invokeTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:207)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.runMethods(PowerMockJUnit44RunnerDelegateImpl.java:146)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$1.run(PowerMockJUnit44RunnerDelegateImpl.java:120)
at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:33)
at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:45)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.run(PowerMockJUnit44RunnerDelegateImpl.java:118)
at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:104)
at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:53)
at org.powermock.modules.junit4.PowerMockRunner.run(PowerMockRunner.java:53)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
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)
Caused by: java.lang.NullPointerException
at com.github.cleverage.elasticsearch.IndexService.(IndexService.java:45)
... 36 more
我在嘲笑我的TaskEntity类,以避免初始化我的搜索引擎。然而,正如我所看到的,即使我想嘲笑它,它也会试图访问它不应该访问的东西。有办法避免这种情况吗?有没有一种方法可以模拟TaskEntity并以某种方式忽略"查找"字段?感谢您的帮助!
我认为简单的解决方案是模拟IndexUtils.getInstanceIndex(type)
调用。这看起来像是一个静态调用,它正在设置t
变量,然后尝试在下一行t.getIndexPath();
中使用该变量。当模拟静态IndexUtils
时,请确保在@PrepareForTest
注释中至少包含IndexUtils
和Finder
。这需要在您的setUp()
中处理,但在您尝试和initMocks(this)
之前。这样,当执行到达错误行时(在初始化TaskEntity
模拟时),它将有钩子返回正确的模拟值,以继续设置。
如果您希望代码根本不进入Finder
构造函数,那么可能还需要一些困难。您的设置必须进行一些更改才能处理静态。确保在@PrepareTest
注释中仍然包括Finder
和TaskEntity
。
@Mock
private TaskEntity taskEntity;
@Mock
private Finder findMock;
@Before
public void setUp() throws Exception {
PowerMockito.mockStatic(Finder.class);
PowerMockito.whenNew(Finder.class).withArguments(TaskEntity.class).thenReturn(findMock);
MockitoAnnotations.initMocks(this);
}
@Test
public void emptyTest(){
}
上面的代码有点棘手,我不确定它是否适用于您。我在本地创建一些shell类以进行测试时遇到了问题。我试图简化您提供的对象,但我仍在努力掌握您所拥有的所有复杂对象之间的设置和相关性。如果有任何错误,请告诉我,我可以尝试调试它们。