首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在Whitebox中实例化抽象类,以便用测试逻辑替换方法,在这里我可以操作参数

如何在Whitebox中实例化抽象类,以便用测试逻辑替换方法,在这里我可以操作参数
EN

Stack Overflow用户
提问于 2017-09-20 15:48:50
回答 2查看 412关注 0票数 0

序言(请阅读):

  • 处理的遗留代码,如果没有国会的行动,我就不能重构(但我有源代码)。
  • 这个遗留代码与交互--许多抽象类--(及其各种实现)
  • 模拟是不够的,因为我需要拦截发送给抽象方法的方法参数,并在替换(测试)逻辑中对它们进行操作。
  • 我知道,我可以将扩展到测试包上的抽象类,并为我想要替换的方法提供实现。然而,这个问题的目标是看看是否有办法绕过它,因为对于有大量抽象方法的抽象类(比如NIO中的SocketChannel ),这是一堆无用的样板代码,使单元测试不可读。
  • 我知道,--遗留代码--设计很差,这不是编写干净、设计良好的单元测试的方法;这是毫无疑问的。只要知道遗产代码是不可能轻易改变的。

的问题是:如何做到这一点(使用 PowerMock )而不从PowerMock获得异常,比如不能实例化该类,因为它是抽象的:

代码语言:javascript
复制
@PrepareForTest({SocketChannel.class})
@RunWith(PowerMockRunner.class)
public class TestThatUsesSocketChannelChannel
{
    replace(method(SocketChannel.class, "read", ByteBuffer.class)).with((proxy, method, args) -> 
    {
        // Line below intercepts the argument and manipulates it 
        ((ByteBuffer) args[0]).clear();
    });
    // The line below throws an exception (because SocketChannel is abstract)
    SocketChannel socketChannel = Whitebox.newInstance(SocketChannel.class);
    // Once here, ideally I can continue my test
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-09-21 14:50:18

找到了答案:因为SocketChannel是一个抽象类,为了使用Whitebox.newInstance,需要对ConcreteClassGenerator进行初步步骤。这将创建一个具有空方法实现的SocketChannel的运行时子程序。注意,在此之前,我替换了我所关心的方法。结论:这允许我实例化抽象类的子类(一个动态的),而不必显式地扩展它。请参阅上面的代码,现在要使用这样的中间步骤:

代码语言:javascript
复制
@PrepareForTest({SocketChannel.class})
@RunWith(PowerMockRunner.class)
public class TestThatUsesSocketChannelChannel
{
    replace(method(SocketChannel.class, "read", ByteBuffer.class)).with((proxy, method, args) -> 
    {
        // Line below intercepts the argument and manipulates it 
        ((ByteBuffer) args[0]).clear();
    });
    // THIS Fixes it: generate a an on-the-fly class that implements stub methods
    // for the ones that are abstract and then (and only then) pass that to Whitebox
    Class<?> concreteSocketChannelClass = new ConcreteClassGenerator().createConcreteSubClass(SocketChannel.class);
    SocketChannel socketChannel = (SocketChannel) Whitebox.newInstance(concreteSocketChannelClass);
    // Once here, ideally I can continue my test
}
票数 0
EN

Stack Overflow用户

发布于 2017-09-20 16:21:25

您可以简单地通过使用普通的Mockito来模拟抽象类:

代码语言:javascript
复制
AbstractClass theMock = mock(AbstractClass.class);

然后通过PowerMock注入这个抽象类的模拟。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46326543

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档