2

我有一个类扩展了我不拥有的另一个类。我的类用于计算对父类的许多调用中的一些度量。有没有一种方法可以在单元测试中模拟父类(同时保留我孩子的逻辑),以确保对我孩子的调用总是“通过”到被包装的父类?

在代码中

Class SlowClass {
    public Object doFoo(Object obj) {
        //...
    }
    public Object doBar(Object obj) {
        //...
    }

    // Many more methods I don't care about.

}

Class SlowClassWrapper extends SlowClass {
    public Object doFoo(Object obj) {
        //...
        Object toReturn = super.doFoo(obj)
        //...
        return toReturn;
    }
    public Object doBar(Object obj) {
        //...
        Object toReturn = super.doFoo(obj)
        //...
        return toReturn;
    }
}

我想以某种方式模拟出来,SlowClass.doFoo以便在SlowClassWrapper.doFoo不实际拨打电话的情况下拨打其父母电话。然后我想确认它obj通过了原样,并且SlowClass.doFoo回复原样返回。

4

2 回答 2

4

一般来说,这不是模拟框架在 Java 中可以愉快地做的事情。您可能需要考虑重组代码以使用组合而不是继承。然后,您可以将 SlowClass 实例注入到包装器的构造函数中,从而通过常规模拟实现轻松的可测试性。

对于它的价值,Mockito 和 PowerMock 都不能模拟超级方法:请参阅这个答案这个讨论

于 2012-11-14T06:47:44.367 回答
1

我会做这样的事情:

public class SlowClassWrapper {
    /** wrapped parent */
    public final SlowClass parent;

    public SlowClassWrapper() {
        this(new SlowClass());

    @VisibleForTesting
    protected SlowClassWrapper(SlowClass parent) {
        this.parent = parent;
    }

    public Object doFoo(Object obj) {
        //...
        Object toReturn = parent.doFoo(obj)
        //...
        return toReturn;
    }

    public Object doBar(Object obj) {
        //...
        Object toReturn = parent.doFoo(obj)
        //...
        return toReturn;
    }
}

使用Mockito和 JUnit

@RunWith(MockitoJUnitRunner.class)
public class SlowClassWrapperTest {
     /** parent mock */
     @Mock
     private SlowClass parentMock;

     /** instance under tests */
     private SlowClassWrapper instance;

     @Before
     public void setUp() {
         this.instance = new SlowClassWrapper(this.parentMock);
     }

     @Test
     public void testDoFoo() {
         final Object obj1 = new Object();
         final Object obj2 = new Object();
         Mockito.doReturn(obj2).when(this.parentMock).doFoo(Matchers.any());
         assertEquals(obj2, this.instance.doFoo(obj1));
         Mockito.verify(this.parentMock).doFoo(obj1);
         Mockito.verifyNoMoreInteractions(this.parentMock);
     }

     @Test
     public void testDoBar() {
         final Object obj1 = new Object();
         final Object obj2 = new Object();
         Mockito.doReturn(obj2).when(this.parentMock).doBar(Matchers.any());
         assertEquals(obj2, this.instance.doBar(obj1);
         Mockito.verify(this.parentMock).doBar(obj1);
         Mockito.verifyNoMoreInteractions(this.parentMock);
     }
}

(未测试)

于 2012-11-14T06:54:37.183 回答