在 JAVA 中使用 Mockito 模拟依赖 class

Mocking a dependent class using Mockito in JAVA

我对 Mockito 很陌生。如果我的问题听起来很愚蠢,我深表歉意。我有一个独立的 JAVA 应用程序,我必须使用 JUnit 和 Mockito 为其编写单元测试用例。重要的是我不能更改代码,因为它是由其他人编写的并且集成测试已经完成。我试图搜索类似的问题,但找不到任何东西。在有些类似的问题中建议的解决方案没有用:(

我已经附加了流量控制diagram.I想模拟依赖类。例如,当我进行单元测试 'Class 1 --> Method 1' 时,我想在不调用它的情况下模拟 'Method 2 in Class 2' 的输出。我试过使用 Mockito.when 和 Mockito.doReturn。两者都调用依赖方法。

有人可以向我提出一些实现此目标的想法吗?

//Pseudocode of Class 1
public class Class1 {
    public boolean method1() {
        Class2 c2 = new Class2();
        boolean b1 = c2.method2();
    }
}

//Pseudocode of Class 2
public class Class2 {
    public boolean method2() {
        Class3 c3 = new Class3();
        boolean b2 = c3.method3();
    }
}

... Likewise same for Class 3, 4 and 5

有时,代码并不是为了测试而编写的。

尤其是在方法或其他构造函数中调用构造函数是单元测试和模拟的一个大问题。

如果您不以任何方式使用工厂或依赖倒置/依赖注入,您将很难测试代码。这也是CDI如此受欢迎的原因之一。

无论如何,在集成测试已经到位后被要求编写单元测试是一种难闻的气味。您应该先编写单元测试。如果您遵循测试驱动开发 (TDD),您应该在实际编写 class 之前就已经编写了测试。这样,就不可能编写 class 难以测试的代码。

但是你已经搞砸了怎么办?

  • 我建议重构您的代码。不要在方法内部调用构造函数,而是将实例传递到方法中,或者在 class 中提供一个字段以便能够模拟它。
  • 重新考虑单元测试的范围。它应该只测试一个 class。其他一切,所有依赖项都应该被模拟。

您被要求做的是为逻辑编写单元测试,该逻辑是由对编写可测试性代码一无所知的人编写的。可能是一位编写代码很长时间的开发人员,以 "old school" 的方式做事,并且认为他太重要了,无法编写单元测试。编写您正在测试的逻辑的人需要回到学校学习一些新技巧。

无论如何这对你没有帮助,所以你仍然可以对这个逻辑进行单元测试,只是比较麻烦。单独使用 Mockito 是做不到的,你需要 "PowerMockito" 来模拟 Class2 的构造。

首先,您需要向项目添加 2 个新的测试依赖项 "powermock-api-mockito"+"powermock-module-junit4".

针对您的案例的测试 class 类似于:

@RunWith(PowerMockRunner.class)
@PrepareForTest(Class1.class)
public class Class1Test {
    private Class1 testSubject;

    @Mock 
    private Class2 class2;

    @Test
    public void testMethod1() throws Exception {
        testSubject.method1();
        verify(class2).method2();
    }

    @Before 
    public void setup() throws Exception {
        MockitoAnnotations.initMocks(this);
        PowerMockito.whenNew(Class2.class).withNoArguments().thenReturn(class2);
        testSubject = new Class1();
    }
}

正如您所见,PowerMockito 允许您使用 PowerMockito.whenNew() 在新的 Class2 实例上模拟构造,这仅在您 "prepared" 使用注释 @PrepareForTest(Class1.class) 的 Class1 时才有效否则 Class1 不能注入模拟 Class2 实例。希望这能为您指明正确的方向?附带一提,如果你是一名初级开发人员,被要求为更高级的开发人员编写单元测试,那么现在就滚蛋吧,你的开发团队已经烂透了!