2014-04-23 52 views
3

我試圖解決這個問題已經兩天了! 這裏是東西:我有如下的類:如何在我的示例中模擬一個具有靜態字段的類?

 

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

    } 
} 
 

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 

 

我在嘲笑我的TaskEntity類,以避免初始化我的搜索引擎。然而,正如我可以看到,即使我想嘲笑它嘗試訪問它不應該的東西。有沒有辦法避免這種情況?有沒有辦法嘲笑TaskEntity,並以某種方式忽略「查找」字段? 任何幫助表示讚賞!

+0

爲了確保我的問題正確無誤,您想要在最高級別模擬「TaskEntity」?你不想讓代碼進入這個'Finder'構造函數?你想嘲笑一個'TaskEntity'並操縱裏面的'Finder',而不用使用普通的編碼功能來觸發它? – Walls

+0

是的,我不想讓代碼進入這個Finder構造函數。 – Hossein

回答

1

我認爲簡單的解決方案是模擬IndexUtils.getInstanceIndex(type)調用。這看起來像是一個靜態調用,它設置t變量,然後嘗試在下一行t.getIndexPath();中使用該變量。當嘲笑靜態IndexUtils時,請確保在您的@PrepareForTest註釋中至少包含IndexUtilsFinder。這需要在您的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類來進行測試。我嘗試簡化你提供的那些,但我仍然試圖掌握所有複雜對象之間的設置和關聯。如果有任何錯誤,請告訴我,我可以嘗試通過它們進行調試。

相關問題