【问题标题】:Using EasyMock to test a method that constructs another object使用 EasyMock 测试构造另一个对象的方法
【发布时间】:2012-08-30 19:48:20
【问题描述】:

我有这样的方法:

public void MyMethod(int p1, int p2) {
  //some logic here
  MyObject mo = new MyObject(var1,var2);
  int returnedId = mo.doOperation(something);
  //Do something with the returnedId;
}

我想测试这个方法,但我不能模拟构造函数调用,所以围绕它的测试会破坏模块化。我可以用工厂方法或其他东西来做,但因为我只有一个构造函数,所以没有意义。

这通常是如何使用 EasyMock 完成的?

【问题讨论】:

标签: java unit-testing easymock


【解决方案1】:

仅使用 EasyMock 无法做到这一点。但是有一些变通的解决方案,比如使用PowerMock 作为 EasyMock 的扩展,这样你就可以模拟静态方法、构造函数调用、最终方法等。

但在此之前,请仔细分析您的问题。你真的需要在MyMethod 中创建MyObject 吗?一般来说,设计类要好得多,其所有依赖项都作为构造函数参数或通过 setter 传入。这就是通常称为“依赖注入”的模式。通过进行依赖注入,您可以避免像您提到的那样的可测试性问题。

此外,MyMethod 可以将MyObject 作为参数,也可以由工厂获取,正如 Duncan Jones 指出的那样。这两种解决方案通常都比将对象实例化与应用程序逻辑混合更好。

【讨论】:

    【解决方案2】:

    我不确定您是否可以在这里逃脱工厂或将对象作为参数传递。这可能感觉像是一个额外痛苦的世界,但如果您希望模拟对象,您通常必须以特定的风格编写代码。

    我会倾向于工厂方向(当然定义为接口)。 在调用 getMyObject() 时模拟工厂并让它返回您的模拟对象:

    public void myMethod(int p1, int p2, MyObject mo) {
      MyObject mo = factory.getMyObject(...args...);
      int returnedId = mo.doOperation(something);
    }
    
    public interface SomeFactory {    
      MyObject getMyObject(...args...);    
    }
    

    或者您可以创建一个接受MyObject 作为参数的方法的重载版本,但这有点难看:

    // Test this one, mocking 'mo'
    public void myMethod(int p1, int p2, MyObject mo) {
      MyObject mo = new MyObject(var1,var2);
      int returnedId = mo.doOperation(something);
    }
    
    public void myMethod(int p1, int p2) {
      myMethod(p1, p2, new MyObject(...));
    }
    

    【讨论】:

    • 重载方式是我认为的好方式。我曾经使用内部类进行测试,然后我可以将我的重载方法设为私有。这并没有影响我的公共界面,但允许我为我的测试进行更多的 DI。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-10-08
    • 2020-07-08
    • 1970-01-01
    • 2019-07-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多