模拟抽象类并使用 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。

我不知道

有什么方法可以解决这个问题,原因很明显:@InjectMocks适用于被测试的非模拟系统,@Mock适用于模拟协作者,而 Mockito 不是为任何类设计的,以在同一测试中同时填补这两个角色。

请记住,您的@Mock(CALLS_REAL_METHODS)声明本质上是危险的:您正在测试 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 实现,如果您只是想测试 AbstractClass 具有与以前相同的扩展 API,即使没有模拟框架也可以使用它。(对于抽象类来说,这是一个经常被忽视的测试。您甚至可以提取它,因为它可能对其他测试有用:如果要重写单个测试类的抽象行为,可以仅使用单个方法重写创建匿名内部类,也可以设置classUnderTest = spy(classUnderTest);以设置 Mockito 代理和所需的行为。

(请记住,@InjectMocks和@Spy不能可靠地一起使用,如本 GitHub 问题及其链接到的 Google Code 和邮件列表线程中所述。

我在初始化之前发现了一些带有模拟字段的技巧。

@InjectMocks
private AbstractClass abstractClass;
@Mock 
private MockClass mockClass;
@Before
public void init() {
    abstractClass= mock(AbstractClass.class, Answers.CALLS_REAL_METHODS);
    MockitoAnnotations.initMocks(this);
}

也许它会帮助某人。

相关内容

  • 没有找到相关文章

最新更新