模拟父类来测试包装类

时间:2012-11-14 06:33:45

标签: java unit-testing mocking

我有一个类扩展了另一个我不拥有的类。我的类用于计算父类的许多调用中的一些指标。有没有办法可以在单元测试中模拟父类(同时保留我孩子的逻辑),以确保针对我的孩子的调用始终“通过”包裹父母?

代码

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的回复没有受到影响。

2 个答案:

答案 0 :(得分:4)

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

对于它的价值,Mockito和PowerMock都不能嘲笑超级方法:见this answerthis discussion

答案 1 :(得分: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);
     }
}

(未经测试)