PowerMock,功能和用例

即使您不喜欢它,有时您的工作也需要您维护旧版应用程序。 它发生在我身上(幸运的是很少),在遗留代码库中编写单个字符之前,我首先要寻找的是单元测试工具。 大多数时候,我倾向于专注于我需要更改的应用程序部分的代码覆盖率,并尝试尽可能地对其进行改进,即使完全没有单元测试也是如此。

当设计不是最新技术时,就会发生真正的麻烦。 单元测试需要模拟,这仅在依赖项注入(以及初始化方法)使类可以进行单元测试时才是好方法:对于某些遗留应用程序,情况并非如此,在这些应用程序中,一堆私有和静态方法或初始化代码构造函数,更不用说静态块了。

例如,考虑以下示例:

publicclassExampleUtils{
    publicstaticvoiddoSomethingUseful(){...}
}

publicclassCallingCode{
    publicvoidcodeThatShouldBeTestedInIsolation(){
        ExampleUtils.doSomethingUseful();
        ...
    }
}

无法正确地对codeThatShouldBeTestedInIsolation()方法进行单元测试,因为它依赖于另一个类的另一个不可模拟的静态方法。 当然,有成熟的技术可以克服这一障碍。 一种这样的技术是创建一个“代理”类,该类将对静态方法的调用包装起来,并将该类注入调用类中,如下所示:

publicclassUsefulProxy{
    publicvoiddoSomethingUsefulByProxy(){
        ExampleUtils.doSomethingUseful();
    }
}

publicclassCallingCodeImproved{
    privateUsefulProxyproxy;
    publicvoidcodeThatShouldBeTestedInIsolation(){
        proxy.doSomethingUSeful();
        ...
    }
}

现在,我可以注入一个模拟的UsefulProxy并最终UsefulProxy测试我的方法。 但是,有几个缺点需要考虑:

  • 产生的代码没有提供测试,只是提供了使测试成为可能的一种方法。
  • 在编写此小替代方法时,您没有进行任何测试。 在这一点上,您什么都没做。
  • 您在测试之前更改了代码,并冒着破坏行为的风险! 当然,该示例并不意味着任何复杂性,但在现实生活中并非总是如此。
  • 您使代码更具可测试性,但又增加了一层复杂性。

由于所有这些原因,我只建议将此方法作为最后的手段。 更糟糕的是,有些设计完全不支持简单的重构,例如以下显示静态初始化程序的示例:

publicclassClassWithStaticInitializer{
    static{...}
}

一旦类加载器加载了ClassWithStaticInitializer类,就将执行静态块,无论是好是坏(根据单元测试,很可能是后者)。

我选择的模拟框架是Mockito 。 它的设计人员确保没有静态方法模拟之类的功能,对此我深表感谢。 这意味着如果我不能使用Mockito,那是设计的味道。 不幸的是,正如我们之前所见,处理遗留代码可能需要这些功能。 那是进入PowerMock的时候(只有那时-在标准的开发过程中使用PowerMock也是确定设计可疑的标志)。

使用PowerMock,您可以保持原始代码不变,并且仍然可以进行测试以放心地开始更改代码。 这是使用Mockito和TestNG的第一个旧代码段的测试代码:

@PrepareForTest(ExampleUtils.class)
publicclassCallingCodeTest{

    privateCallingCodecallingCode;

    @BeforeMethod
    protectedvoidsetUp(){
        mockStatic(ExampleUtils.class);
        callingCode=newCallingCode();
    }

    @ObjectFactory
    publicIObjectFactorygetObjectFactory(){
        returnnewPowerMockObjectFactory();
    }

    @Test
    publicvoidcallingMethodShouldntRaiseException(){
        callingCode.codeThatShouldBeTestedInIsolation();
        assertEquals(getInternalState(callingCode,"i"),1);
    }
}

没有什么可做的,即:

  • 使用@PrepareForTest注释测试类(或单个测试方法), @PrepareForTest引用类或整个程序包。 这告诉PowerMock允许对这些类进行字节码操作,有效指令将在下一步中完成。
  • 使用可用的mockXXX()方法面板模拟所需的方法。
  • 在返回IObjectFactory并用@ObjectFactory注释的方法中提供对象工厂。

还要注意,借助Whitebox类,我们可以访问类的内部状态( 私有变量)。 即使这很糟糕,也可以选择-在没有测试工具的情况下使用遗留代码的机会更糟:记住我们的目标是减少引入新错误的机会。

PowerMock的功能列表在此处可用于Mockito。 请注意,目前无法使用TestNG抑制静态块。

您可以在此处以Maven格式找到本文的资源。

翻译自: https://blog.frankel.ch/powermock-features-and-use-cases/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值