【问题标题】:How to mock local variables in java? [duplicate]如何在java中模拟局部变量? [复制]
【发布时间】:2013-04-09 07:11:09
【问题描述】:

在这种情况下?

class A {
  public void f() {
    B b = new B();
    C c = new C();
    // use b and c, and how to modify their behaviour?
  }
}

如何使用PowerMockEasyMock 来实现我的想法?

出于测试原因,我不想更改我的紧凑代码。

【问题讨论】:

    标签: java mocking easymock powermock


    【解决方案1】:

    实际上,您可以使用 PowerMock 模拟对象构造。他们在这里有很好的文档:https://code.google.com/p/powermock/wiki/MockConstructor

    还可以查看 this example ,它介绍了模拟对象的构造。

    【讨论】:

    • +1 当然可以。但这并不意味着我们应该这样做。只是说明一点。
    • @Narendra OP 说“出于测试原因,我不想更改我的紧凑代码”,这在我看来是一个非常好的理由。相反,您似乎建议应该将可以正常工作的简单代码变得更复杂,以避免使用模拟工具...
    • 许多运行良好的简单代码并不适合测试。使代码可测试并不会使其变得复杂。它可以节省您的时间和未来的重新设计。使用这个 powermock hack 并不是一个好方法,只有当创建实例的代码不在我们的控制范围内时才必须这样做,即属于一个库左右。
    • 我不同意使用这种方法的唯一时间是当代码不受我们控制时。在软件开发中,有时 时间表 不在我们的控制范围内,有 any 测试总比没有好。如果我必须停止并重构所有代码,使其在我可以将其包装在单元测试中之前“对测试友好”,那么我可能永远不会编写任何测试。
    • @MattLachman - 当用于对象创建的类是最终的时,我如何使其工作。我收到错误:“不能继承最终类”
    【解决方案2】:

    您可以这样做,请参阅 Matt Lachman 的答案。但是不推荐这种方法。这有点hacky。

    最好的方法是将您的依赖对象的创建委托给工厂模式并将工厂注入您的A 类:

    class BFactory {
    
        public B newInstance() {
            return new B();
        }
    }
    
    class CFactory {
    
        public C newInstance() {
            return new C();
        }
    }
    
    class A {
    
        private final BFactory bFactory;
        private final CFactory cFactory;
    
        public A(final BFactory bFactory, final CFactory cFactory) {
            this.bFactory = bFactory;
            this.cFactory = cFactory;
        }
    
        public void f() {
            B b = bFactory.newInstance();
            C c = cFactory.newInstance();
        }
    }
    

    然后您将模拟工厂以返回依赖类的模拟实例。

    如果由于某种原因这不可行,那么您可以在 A 类中创建工厂方法

    class A {
    
        public void f() {
            B b = newB();
            C c = newC();
        }
    
        protected B newB() {
            return new B();
        }
    
        protected C newC() {
            return newC();
        }
    }
    

    然后您可以使用 spy 来模拟这些工厂方法。

    【讨论】:

    • 是的,就像我的回答,但有更多细节
    • 剥猫皮的方法只有这么多。只有几个正确的......
    • “你不能”不是真的。 PowerMock 允许您模拟构造函数。见这里:code.google.com/p/powermock/wiki/MockConstructor
    • 它是否是肮脏的黑客(主观)无关紧要。提问者问是否可能;它是。我原则上同意你的方法更好。
    • 正如马特已经指出的那样,这个答案是错误的。问题清楚地表明“我怎样才能用 PowerMock 和 EasyMock 实现我的想法?”,这绝对是可能的。
    【解决方案3】:

    如果不更改代码,它将无法正常工作。 (可测试性设计)。 您可以将 B 替换为工厂方法,该方法在实际中创建 B1,或在测试中创建 BTest,两者都实现了 IB 接口。

    【讨论】:

      【解决方案4】:

      看来你需要Dependency Injection

      您正在创建 B 和 C 的具体实例,那么您无法修改行为。

      将实例作为参数传递给f(InterfaceB b, InterfaceC c),您应该利用多态性,然后您可以将需要更改其行为的模拟实例作为参数传递给此方法。所以该方法不需要关心它传递给它的具体实例类型,你可以实现你所需要的。

      我知道接口的名称不合逻辑,但可以很容易地解释上下文。

      【讨论】:

      • 好的,谢谢大家
      • @user988722 你明白我要解释的意思了吗?
      • 我想我得到了:1。如果不更改代码,我将无法实现我的想法。 2. 我必须重构我的代码让 B 和 C 传入。对吗?
      • 是的!它类似于给出的工厂解决方案。不同之处在于您不是通过工厂,而是使用多态性来实现您想要的,而无需创建任何新类。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-19
      • 1970-01-01
      • 2010-10-02
      • 2012-12-15
      相关资源
      最近更新 更多