2015-08-18 109 views
5

如何使用Mockito或PowerMock來模擬一個由子類實現但從一個抽象超類繼承的受保護方法?如何模仿繼承自抽象類的受保護的子類方法?

換句話說,我想在嘲笑「doSomethingElse」時測試「doSomething」方法。

摘要超類

public abstract class TypeA { 

    public void doSomething() {  

     // Calls for subclass behavior 
     doSomethingElse();  
    } 

    protected abstract String doSomethingElse(); 

} 

子類實現

public class TypeB extends TypeA { 

    @Override 
    protected String doSomethingElse() { 
     return "this method needs to be mocked"; 
    } 

} 

解決方案

這裏給出的答案是正確的如果涉及的類都在同一個包中,d將會工作。

但是如果涉及不同的包一個選項是用戶PowerMock。下面的例子爲我工作。當然,也可能有其他方式來做到這一點,這是一個有效的方法。

import static org.junit.Assert.assertEquals; 
import org.junit.Test; 
import org.junit.runner.RunWith; 
import org.powermock.api.mockito.PowerMockito; 
import org.powermock.core.classloader.annotations.PrepareForTest; 
import org.powermock.modules.junit4.PowerMockRunner; 

@RunWith(PowerMockRunner.class) 
@PrepareForTest({ TypeB.class }) 
public class TestAbstract { 

    @Test 
    public void test_UsingPowerMock() throws Exception { 
     // Spy a subclass using PowerMock 
     TypeB b = PowerMockito.spy(new TypeB()); 
     String expected = "some value for mock"; 

     // Mock a method by its name using PowerMock again 
     PowerMockito.doReturn(expected).when(b, "doSomethingElse"); 

     // Calls the 
     String actual = b.doSomething(); 
     assertEquals(expected, actual);  

    } 
} 

注:測試使用Java 5,JUnit的4.11,1.9.0的Mockito和PowerMock 1.4.12完成。

+1

這種方法給了我一個帶有Java 8,JUnit 4.12和PowerMock 1.6.4的'NullPointerException'。 – Mack

回答

5

你可以嘲笑抽象方法時,使用Mockito.CALLS_REAL_METHODS。這將調用類的原始方法,你可以自己模擬所有的抽象方法。

TypeA typeA = mock(TypeA.class, Mockito.CALLS_REAL_METHODS); 
when(typeA.doSomethingElse()).thenReturn("Hello"); 
typeA.doSomething(); 

或者你有一個間諜直接測試上的TypeB:

TypeB typeB = spy(new TypeB()); 
when(typeB.doSomethingElse()).thenReturn("Hello"); 
typeB.doSomething(); 
+1

第一個選項失敗,因爲TypeA是抽象的。選項2與'spy()'一起使用,但是當我嘗試將它應用到我的生產代碼中時,它給了我'來自類型<子類名稱>的方法不可見「。試圖找出原因。 – BonanzaOne

+0

其實你的測試是正確的,但我有不同的包中的類,這就是爲什麼我無法做到這一點。當受保護時,其他軟件包中的方法不可見。 – BonanzaOne

+0

第一個選項也有效嗎?我已經用Mockito 1.10.19和最新的測試版進行了測試,兩者都按預期工作。 – mszalbach

3

您可以在我建議使用爲的Mockito是通過以下方式

TypeA typA = Mockito.mock(TypeA.class, Mockito.CALLS_REAL_METHODS); 
when(typA.doSomethingElse()).thenReturn("doSomethingElse"); 
Assert.assertSomething(typeA.doSomething()); 
4

使用測試的Mockito您abtract類:

// Create a new Mock 
final TypeA a = Mockito.mock(TypeA.class, Mockito.CALLS_REAL_METHODS); 

// Call the method 
a.doSomething(); 

// Now verify that our mocked class' method was called 
Mockito.verify(a, Mockito.times(1)).doSomethingElse(); 
+0

它的工作原理,但我只是意識到,我有我的生產代碼中的不同包中的類。然後,受保護的方法不可見。 – BonanzaOne

+0

這使它成爲一個問題。一個可能的解決方案是使用PowerMock,它應該能夠驗證私有方法afaik。雖然從未使用過。 –

2

嘲笑方法返回void在抽象類中,我們可以使用:

MyAbstractClass abs = Mockito.mock(MyAbstractClass.class); 
Mockito.doNothing().when(abs).myMethod(arg1,arg2....)); 

我們可以將其替換參數Mockito.anyString()等按要求。

相關問題