2016-01-25 121 views
2

是否可以模擬抽象類並使用Mockito註釋將其注入模擬類。我現在有以下情況:嘲笑抽象類並使用Mockito註釋注入類?

@Mock private MockClassA mockClassA; 
@Mock private MockClassB mockClassB; 

@Mock(answer = Answers.CALLS_REAL_METHODS) private AbstractClassUnderTest abstractClassUnderTest; 

@Before 
public void init() { 
    MockitoAnnotations.initMocks(this); 
    Whitebox.setInternalState(abstractClassUnderTest, mockClassA); 
    Whitebox.setInternalState(abstractClassUnderTest, mockClassB); 
} 

我想使用類似的AbstractClassUnderTest @InjectMocks但不能與@Mock組合使用。目前的情況,使用Powermock的Whitebox,可行,但我很好奇,如果可以用註釋解決它。我找不到任何解決方案或例子。

(我知道反對測試抽象類和我個人,而測試的具體實施,只是使用@InjectMocks。)

回答

4

我不知道有任何的方式去這一點,一個清晰理由:@InjectMocks適用於被測試的非模擬系統,而@Mock適用於模擬協作者,Mockito不適用於任何類在同一測試中填充這兩個角色。

請注意,您的@Mock(CALLS_REAL_METHODS)聲明爲inherently dangerous:您正在測試AbstractClassUnderTest,但未運行任何構造函數或初始化任何字段。我不認爲你可以期望這個設計的測試是現實的或強健的,無論註釋能夠或不能爲你做什麼。 (就我個人而言,我以前贊成真正的抽象類的部分模仿作爲「工具箱中的工具」,但是我現在認爲它們離現實太遠以至於無法使用。)

我在你的位置,我會創建一個用於測試的小覆蓋的實現:

@RunWith(JUnit4.class) public class AbstractClassTest { 
    /** Minimial AbstractClass implementation for testing. */ 
    public static class SimpleConcreteClass extends AbstractClass { 
    public SimpleConcreteClass() { super("foo", "bar", 42); } 
    @Override public void abstractMethod1() {} 
    @Override public String abstractMethod2(int parameter) { return ""; } 
    } 

    @InjectMocks SimpleConcreteClass classUnderTest; 
    @Mock mockClassA; 
    @Mock mockClassB; 
} 

在這一點上,你有一個簡單的和可預見的抽象類實現,如果你只是想測試你甚至可以使用不帶模擬框架該AbstractClass具有與之前相同的擴展API。 (這是抽象類經常被忽視的測試。)你甚至可以提取它,因爲它可能對其他測試有用:如果你想覆蓋單個測試類的抽象行爲,你可以創建一個匿名內部類只需一個方法覆蓋,或者您可以設置classUnderTest = spy(classUnderTest);來設置Mockito代理和您想要的行爲。

(記住,@InjectMocks和@Spy不能可靠一起使用,如與它連接this GitHub issue與谷歌代碼和郵件列表線程記錄。)