【问题标题】:mocking abstract classes [duplicate]模拟抽象类[重复]
【发布时间】:2011-12-31 13:17:36
【问题描述】:

可能重复:
Using Mockito to test abstract classes

我有一个具有我需要测试的功能的抽象类。我可以在没有抽象方法的操作实现的情况下创建该类的简单派生,但是可以使用模拟框架来完成吗?我需要维护类内部状态,所以我不能只是调用

mockedInstance = mock(ClassUnderTest.class);

我需要一些东西

mockedInstance = spy(new ClassUnderTest(...));

但显然这是不可能的,因为类是抽象的。

【问题讨论】:

标签: java mocking mockito powermock


【解决方案1】:

当我想对一个我不模拟的抽象类进行单元测试时,我将其子类化。

在其他答案中从 mijer 借用代码

public class MockitoTest {
    public static abstract class MyAbstractClass {
       private int state;
       public abstract int abstractMethod();

       public int method(....)
       {
        ...
       }
    }
}


class Testclass extends MyAbstractClass 
{
      public int abstractMethod()
      {
       ...
      }
 }

然后使用 Testclass 的实例运行您的 MyAbstractClass 测试。 您可以控制本地子类中抽象方法的实现。

【讨论】:

  • 意图不是扩展一个类,而是使用一个模拟框架
  • 应避免这种方法,因为您不再测试类,而是测试子类,并且可能会掩盖或引入错误。随着测试被添加到测试夹具中,它也无法很好地扩展。
【解决方案2】:
import org.junit.Test;
import org.mockito.internal.stubbing.answers.CallsRealMethods;

import static org.mockito.Mockito.*;
import static org.junit.Assert.*;

public class MockitoTest {
    public static abstract class MyAbstractClass {
        private int state;
        public abstract int abstractMethod();
        public void method() {
            System.out.println("method. State: " + (++state));
            System.out.println("abstractMethod: " + abstractMethod());
            anotherMethod();
        }
        public void anotherMethod() {
            System.out.println("anotherMethod. State: " + (++state));
        }
    }

    @Test
    public void test() throws Exception {
        MyAbstractClass obj = mock(MyAbstractClass.class, new CallsRealMethods());
        doReturn(5).when(obj).abstractMethod();

        obj.method();

        verify(obj).abstractMethod();

        assertEquals(2, obj.state);
    }
}

-编辑-

  1. 如果你需要维护对象的内部状态你必须使用org.mockito.internal.util.reflection.Whitebox.setInternalState,例如:

    @Test
    public void test() throws Exception {
        MyAbstractClass obj = mock(MyAbstractClass.class, new CallsRealMethods());
        setInternalState(obj, "state", 100);
        doReturn(5).when(obj).abstractMethod();
    
        obj.method();
    
        verify(obj).abstractMethod();
        assertEquals(102, obj.state);
    }
    
  2. 1234563

【讨论】:

  • 如果我需要将参数传递给构造函数怎么办?
  • 这样设置内部状态有点麻烦。在实际示例中,可能会有更多的变量、复杂的逻辑等。
  • 这意味着您应该以某种方式简化/重构您的代码,使其更易于测试和理解。此外,这是一个很好的做法。为什么需要调用构造函数而不是测试类方法?
  • 我在构造函数中有初始化逻辑,需要先执行才能测试方法。
  • 在这种情况下,您必须测试真实类而不是抽象类。我想几乎不可能扩展一个抽象类,在生成的类中生成所有对应的构造函数,添加对超类构造函数的调用,然后用当前的模拟框架实现所有抽象方法。
猜你喜欢
  • 2016-12-05
  • 2012-06-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多