【问题标题】:Mocking a dependent class using Mockito in JAVA在 JAVA 中使用 Mockito 模拟依赖类
【发布时间】:2020-03-30 03:03:16
【问题描述】:

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

我附上了流程控制图。我想模拟依赖类。例如,当我对“Class 1 --> Method 1”进行单元测试时,我想模拟“Class 2 中的方法 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

【问题讨论】:

  • 你能分享你的测试代码吗?
  • 问题是你没有使用依赖注入。如果你自己通过调用构造函数来初始化 bean,就很难模拟一个 bean。
  • 正是使用依赖注入的原因。
  • 不使用 PowerMock,我没有办法做你想做的事
  • 在功能齐全的实现和集成测试到位后编写单元测试是一件非常糟糕的事情。基本上,我要说的是:你做错了。或者有人强迫你做错了:(

标签: java mockito powermock stub


【解决方案1】:

您被要求做的是为逻辑编写单元测试,这些逻辑是由完全不知道为测试能力编写代码的人编写的。可能是一个编写代码很长时间的开发人员,以“老派”的方式做事,并认为他太重要了,无法编写单元测试。编写您要测试的逻辑的人需要回到学校学习一些新技巧。

无论如何这对你没有帮助,所以你仍然可以对这个逻辑进行单元测试,只是更痛苦。单靠 Mockito 是做不到的,你需要“PowerMockito”,它可以让你模拟 Class2 的构造。

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

您的案例的测试类看起来像:

@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 实例上模拟构造,这仅在您使用注释 @PrepareForTest(Class1.class) “准备” Class1 时才有效,否则 Class1 无法注入模拟 Class2 实例。希望这为您指明了正确的方向?附带说明一下,如果您是初级开发人员,现在被要求为更高级的开发人员编写单元测试,那么您的开发团队很烂!

【讨论】:

  • 非常感谢约翰·斯金格。这正是我一直在寻找的。它奏效了。
  • 虽然这个答案可以测试它,但也这样做并不是一个好主意。而是重构代码,以便在此过程中轻松测试和学习如何正确设计软件。至少这将是我对我指导的每个人的建议。
【解决方案2】:

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

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

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

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-15
    相关资源
    最近更新 更多