简体   繁体   English

如何在我的示例中模拟一个具有静态字段的类?

[英]How can I mock a class that has a static field in my example?

It's been two days that I am trying to solve this! 我试图解决这个问题已经两天了! Here is the thing: I have a Class as below: 事情就是这样:我有一个类如下:


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
}

which extends this abstract class: 它扩展了这个抽象类:


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
    }

}

Simply I try to mock the TaskEntity class without any extra code as below: 我只是尝试模拟TaskEntity类,而不需要任何额外的代码,如下所示:


public class TaskManagementServiceImplTest {
    @Mock
    private TaskEntity taskEntity;

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void emptyTest(){

    }
}

BOOM: 繁荣:


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

I am mocking my TaskEntity class to avoid initializing my search engine. 我正在嘲笑我的TaskEntity类,以避免初始化我的搜索引擎。 However, as I can see even when I want to mock it it tries to access stuff that it shouldn't. 但是,正如我所知,即使我想模仿它,它也试图访问不应该的东西。 Is there a way to avoid this? 有办法避免这种情况吗? Is there a way to mock TaskEntity and somehow ignoring that "find" field? 有没有办法模拟TaskEntity并以某种方式忽略该“查找”字段? Any help is appreciated! 任何帮助表示赞赏!

I think the easy solution is to mock the IndexUtils.getInstanceIndex(type) call. 我认为简单的解决方案是模拟IndexUtils.getInstanceIndex(type)调用。 That looks like a static call which is setting that t variable, which is then trying to be used in the next line t.getIndexPath(); 这看起来像是一个静态调用,它设置了t变量,然后尝试在下一行中使用t.getIndexPath(); . When mocking the static IndexUtils , make sure to include in your @PrepareForTest annotation at least IndexUtils and Finder . IndexUtils静态IndexUtils ,请确保在@PrepareForTest注释中至少包含IndexUtilsFinder This would need to be handled in your setUp() but before you try and initMocks(this) . 这需要在setUp()处理,但在尝试initMocks(this) That way, when the execution gets to the error line (upon initialization of the TaskEntity mock) it will have the hooks to return the proper mocked values to continue with the setup. 这样,当执行到达错误行时(在初始化TaskEntity模拟时),它将有钩子返回正确的模拟值以继续设置。

If you want the code to not go into the Finder constructor at all, it could take a few more hoops to jump through. 如果你希望代码根本不进入Finder构造函数,可能需要更多的箍才能跳过。 Your setup would have to change a bit to handle the static. 你的设置必须改变一点来处理静态。 Make sure to still include Finder as well as TaskEntity in your @PrepareTest annotation. 确保仍然包括Finder以及TaskEntity@PrepareTest注释。

@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(){

}

This above code is a little tricky and I am not sure if it will work for you. 上面的代码有点棘手,我不确定它是否适合你。 I am having trouble creating some shell classes locally to do testing with. 我无法在本地创建一些shell类来进行测试。 I tried simplifying the ones you provided but I am still trying to grasp the setup and correlation between all the complex objects you have. 我尝试简化你提供的那些,但我仍然试图掌握你拥有的所有复杂对象之间的设置和相关性。 If there are any errors with this, let me know and I can try and debug through them. 如果有任何错误,请告诉我,我可以尝试通过它们进行调试。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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