我试图解决这个问题已经两天了!
事情就是这样:我有一个类如下:
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类来进行测试.我尝试简化你提供的那些,但我仍然试图掌握你拥有的所有复杂对象之间的设置和相关性.如果有任何错误,请告诉我,我可以尝试通过它们进行调试.