簡體   English   中英

在沒有子類化抽象類的情況下模擬對抽象類的公共方法的調用,優先使用mockito

[英]Mocking a call on a public method of an abstract class without subclassing the abstract Class, using mockito prefererably

我正在編寫一個使用JUNIT + Mockito測試方法的單元測試:

public someObject methodUnderTest(){
  SomeObject obj = SomeAbstractClass.someMethod();

  if(obj!=null){
    obj.someOtherMethod();
  }

  return someThing;
}

我想在上面的代碼片段中提到的abstract Class "SomeAbstractClass"上模擬調用,這樣我就可以驗證對“obj”的調用,如:

verify(SomeAbstractClass).someMethod();
verify(obj).someOtherMethod();

我嘗試過使用mockito功能,例如:Mockito.CALLS_REAL_METHODS Mockito.RETURNS_MOCKS

但由於SomeAbstractClass不可用的依賴項,它們不起作用。

注意:

1)SomeObject是一個接口。

2)我需要一種技術來測試上面的代碼片段。 我被限制使用上面的代碼片段,不能更改代碼片段。

您可以使用PowerMock來模擬靜態和最終方法。

聽起來問題是您對CALLS_REAL_METHODS的使用正在應用於整個類,您真正想要模擬特定方法(即進行“部分模擬”)。 這里有兩個選項,一個使用thenCallRealMethod ,一個使用CALLS_REAL_METHODS ,然后專門CALLS_REAL_METHODS你需要的調用:

public void testMethodUnderTest_mockSpecificThings() {
    SomeAbstractClass myAbstractClass = Mockito.mock(SomeAbstractClass.class);
    SomeAbstractClass myObject = Mockito.mock(SomeObject.class);
    when(myAbstractClass.someMethod()).thenReturn(foo);
    when(myAbstractClass.methodUnderTest()).thenCallRealMethod();

    myAbstractClass.methodUnderTest();

    verify(myAbstractClass).someMethod();
    verify(myObject).someOtherMethod();
}

public void testMethodUnderTest_makeSpecificRealCalls() {
    SomeAbstractClass myAbstractClass =
        Mockito.mock(SomeAbstractClass.class, CALLS_REAL_METHODS);
    SomeAbstractClass myObject = Mockito.mock(SomeObject.class);
    // overrides the default answer
    when(myAbstractClass.someMethod()).thenReturn(myObject);

    myAbstractClass.methodUnderTest();

    verify(myAbstractClass).someMethod();
    verify(myObject).someOtherMethod();
}

預先警告SomeAbstractClass從未實際實例化,因此如果您依賴於抽象類構造函數中的任何行為,如變量初始化 - 包括聲明字段的內聯初始化 - 您將需要自己明確地進行這些調用。

使用匿名類:

public interface SomeObject {
     public Object someOtherMethod();
}

public abstract class SomeAbstractClass {
    abstract SomeObject someMethod();
}

@Test
public void test() {
    SomeAbstractClass target = new SomeAbstractClass() {
        SomeObject someMethod() {
            // some impl
            SomeObject someObject = new SomeObject() {
                public Object someOtherMethod() {
                    // some other impl
                }
            };
            return someObject;
        }
    };

    // now test target
}

假設:如果你編寫單元測試,我猜你還是可以修改一下測試方法。

解:

  1. 提取靜態方法調用可覆蓋的方法:
 public someObject methodUnderTest() { SomeObject obj = getSomeObject(); if(obj!=null){ obj.someOtherMethod(); } return someThing; } protected SomeObject getSomeObject() { return SomeAbstractClass.someMethod(); } 
  1. 那么你可以使用Mockito Spy來部分模擬你實際測試的對象:
 private ClassUnderTest classUnderTest; @Before public void setUp() { classUnderTest= new ClassUnderTest(); classUnderTest = Mockito.spy(classUnderTest); } @Test public void test() { SomeObject someObject = Mockito.mock(SomeObject.class); when(classUnderTest.getSomeObject()).thenReturn(someObject); classUnderTest.methodUnderTest(); verify(someObject).someOtherMethod(); } @Test public void testNull() { when(classUnderTest.getSomeObject()).thenReturn(null); classUnderTest.methodUnderTest(); verify(something); } 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM