在我的例子中,我如何模拟一个有静态字段的类



我已经两天试图解决这个问题了!事情是这样的:我有一个班级如下:


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注释中至少包含IndexUtilsFinder。这需要在您的setUp()中处理,但在您尝试和initMocks(this)之前。这样,当执行到达错误行时(在初始化TaskEntity模拟时),它将有钩子返回正确的模拟值,以继续设置。

如果您希望代码根本不进入Finder构造函数,那么可能还需要一些困难。您的设置必须进行一些更改才能处理静态。确保在@PrepareTest注释中仍然包括FinderTaskEntity

@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类以进行测试时遇到了问题。我试图简化您提供的对象,但我仍在努力掌握您所拥有的所有复杂对象之间的设置和相关性。如果有任何错误,请告诉我,我可以尝试调试它们。

相关内容

  • 没有找到相关文章

最新更新