2017-06-22 167 views
-1

我需要建立以下情況下的單元測試:被測模擬靜態默認接口方法

類別:

class MyProducer { 

private Producer producer = null; 
private ProducerCreator producerCreator = null; 

public MyProducer() { 
producerCreator = ProducerCreator.create(string name); 
producer = producerCreator.createProducer(); 

} 
public boolean foo() { 
    return producer.foo(); 
} 
} 

類ProducerCreator是從外部包沒有源代碼:

public interface ProducerCreator { 

static default ProducerCreator create(String name) { 
    return new ProducerCreatorImpl(...) 
    } 
} 

所以我試圖嘲弄與PowerMockito的靜態調用:

@RunWith(PowerMockRunner.class) 
@PrepareForTest(ProducerCreator.class) 
public class ProducerTest { 

    @Test 
    public void fooTest() { 


     ProducerCreator producerCreatorMock = Mockito.mock(ProducerCreator.class); 

PowerMockito.mockStatic(ProducerCreator.class); 
PowerMockito.when(ProducerCreator.class, "createProducer", "name").thenReturn(producerCreatorMock); 

(也試過這樣:

PowerMockito.when(ProducerCreator.create("name")).thenReturn(producerCreatorMock); 

但它沒有做任何改變)

 MyProducer myProducer = new MyProducer(); 


    assertTrue(myProducer.foo()); 



} 

一般來說,我得到類似如下:

org.mockito.exceptions.misusing.UnfinishedStubbingException: 
... 
E.g. thenReturn() may be missing. 
Examples of correct stubbing: 
    when(mock.isOk()).thenReturn(true); 
    when(mock.isOk()).thenThrow(exception); 
    doThrow(exception).when(mock).someVoidMethod(); 
Hints: 
1. missing thenReturn() 
2. you are trying to stub a final method, you naughty developer! 
3: you are stubbing the behaviour of another mock inside before 'thenReturn' instruction if completed 

或任何其他錯誤或不必要的行爲,而不是適當的嘲弄。 由於界面中「靜態默認」方法的問題? 在互聯網上沒有找到任何這種情況下的例子。

UPD: 我不能分享真實的代碼,因爲它是專有的。

有來自外部的包真正的靜態默認方法,它編譯:

public interface ProducerCreator extends Closeable { 
    static default ProducerCreator create(String serviceUrl) throws ProducerCreatorException { 
     return ... 
    } 

UPD 2:該軟件包是一個JNI包 - 從CPP代碼生成..

+2

你確定方法是默認和靜態..這組合會導致編譯錯誤。 –

+0

當然,當然。我看到代碼:) –

+2

你不能有一個同時具有'static'和'default'的接口方法。這個「肯定,肯定」告訴我們,你還沒有試圖編譯你的代碼示例,也沒有做盡職調查。 「我看到代碼」甚至意味着什麼?該回應使您的問題無效。 http://docs.oracle.com/javase/specs/jls/se8/html/jls-9.html#jls-9.4「如果一個方法被多個修飾符聲明,那麼這是一個編譯時錯誤'抽象「,」默認「或」靜態「。請告訴我們你的_real_代碼。你展示的內容無法編譯。 –

回答

0

您的代碼不編譯。我已經取得了一些假設:

public class Producer { 
    public boolean foo(){ 
     return true; 
    } 
} 

public interface ProducerCreator { 
    public static ProducerCreator create(String name) { 
     return new ProducerCreatorImpl(name); 
    } 

    Producer createProducer(); 
} 

public class MyProducer { 

    private Producer producer = null; 
    private ProducerCreator producerCreator = null; 

    public MyProducer() { 
     producerCreator = create("name"); 
     producer = producerCreator.createProducer(); 

    } 
    public boolean foo() { 
     return producer.foo(); 
    } 
} 
public class ProducerCreatorImpl implements ProducerCreator{ 


    public ProducerCreatorImpl(String name) { 

    } 

    @Override 
    public Producer createProducer() { 
     return new Producer(); 
    } 
} 

而且你的測試,這對我的作品:

@RunWith(PowerMockRunner.class) 
@PrepareForTest({ ProducerCreator.class }) 
public class DatasourceTest { 

    @Test 
    public void fooTest() { 


     ProducerCreator producerCreatorMock = Mockito.mock(ProducerCreator.class); 

     PowerMockito.mockStatic(ProducerCreator.class); 
     PowerMockito.when(ProducerCreator.create(Mockito.anyString())).thenReturn(producerCreatorMock); 

     Producer prodMock = Mockito.mock(Producer.class); 
     Mockito.when(producerCreatorMock.createProducer()).thenReturn(prodMock); 
     Mockito.when(prodMock.foo()).thenReturn(false); 

     MyProducer myProducer = new MyProducer(); 
     boolean result = myProducer.foo(); 

     Assert.assertFalse(result); 

     Mockito.verify(prodMock).foo(); 

    } 
} 
+0

我放在這裏的代碼是我無法發佈的真實代碼的抽象。 在你的例子中,接口函數是靜態的,但不是默認的。 如果您添加默認關鍵字,它是否工作? –

+0

不,因爲@Macijej對你的問題發表了評論,它不會被編譯。這是靜態和默認的非法組合。我添加了一些更精細的測試,其中測試了一些東西 – kism3t

+0

JNI包怎麼樣? –