【问题标题】:How to mock a static method call on an object in a static method?如何在静态方法中模拟对对象的静态方法调用?
【发布时间】:2016-09-13 14:30:01
【问题描述】:

我是 Junit 测试的新手,但我必须测试一些代码。我想现在我知道了它的基础知识,但是我仍然遇到了一个我在互联网上找不到任何东西的问题:

这是我要测试的课程:

public static void methodToTest(Label l2, Label l3, User u) {


    int first = MyDB.someMethod(u.anotherMethod()).size();
    int second = MyDB.someOtherMethod(u).size();


    if (first == 1) {
        l2.setCaption("...");
    }

    ...
}

我不希望系统创建整数“第一”和“第二”。相反,我只希望它们为“1”,这样我就可以测试最后几行代码是否正常工作。

MyDB 是一个带有静态方法(someMethod() 和 someOtherMethod())的公共类

我想测试方法methodToTest。我尝试使用 parms 调用此方法,最后将修改后的参数与预期的参数进行比较。

我使用 Mockito 和 PowerMockito。

这是我的尝试之一:

@PrepareForTest({ClassToTest.class, MyDB.class })
@RunWith(PowerMockRunner.class)
public class Test extends PowerMockTestCase{
   PowerMockito.mockStatic(MyDB.class);
   PowerMockito.doReturn(1).when(MyDB.someMethod(u.anotherMethod()).size());
   PowerMockito.doReturn(1).when(MyDB.someOtherMethod(u).size());
   ClassToTest.methodToTest(l1, l2, u);
   assertTrue(l1.equals(l3) && l2.equals(l4));
}

我得到的例外是: '传递给 when() 的参数不是模拟!'

我希望任何人都可以帮助我。我花了这么多小时来解决这个问题,但没有成功。

谢谢!!!

【问题讨论】:

  • 当然你可以模拟静态方法,但是摆脱它们以及它们带来的不方便的隧道依赖不是更好吗?这就是我的建议:避免使用静态方法。如果您正在使用其他人的代码并且在围绕它进行测试之前不会对其进行重构,那么您可能会发现像 JMockit 这样的工具比 Mockito 和 PowerMockito 更容易使用。

标签: unit-testing junit static-methods powermockito static-class


【解决方案1】:

正如我在评论中提到的,您发现静态方法是测试的障碍。所以,我建议你避免使用静态方法。让我们看看在您的示例中可能是什么样子:

你有一些代码需要测试..

public class ProductionClass {
  public static void methodToTest(Label l2, Label l3, User u) {
    int first = MyDB.someMethod(u.anotherMethod()).size();
    int second = MyDB.someOtherMethod(u).size();

    if (first == 1) {
        l2.setCaption("...");
    }

    ...
  }
}

首先,将生产类的静态方法设为实例方法:

public class ProductionClass {
  public void methodToTest(Label l2, Label l3, User u) {  // removed "static"
    int first = MyDB.someMethod(u.anotherMethod()).size();
    int second = MyDB.someOtherMethod(u).size();

    if (first == 1) {
        l2.setCaption("...");
    }

    ...
  }
}

好的,所以您仍然可以耦合到 MyDB 上的静态方法。摆脱那个静态方法只会让你的生产类更容易测试。下面是如何......你可以像这样进行一些提取方法重构:

public class ProductionClass {
  public void methodToTest(Label l2, Label l3, User u) {
    int first = getFirst();
    int second = getSecond();

    if (first == 1) {
        l2.setCaption("...");
    }

    ...
  }

  int getFirst() {
    return MyDB.someMethod(u.anotherMethod()).size();
  }

  int getSecond() {
    return MyDB.someOtherMethod(u).size();
  }
}

现在您可以轻松地继承该生产类并覆盖(或部分模拟,如果您愿意的话)您想要使用的方法..

public class TestableProductionClass extends ProductionClass {
  @Override
  int getFirst() {
    return 1;
  }

  @Override
  int getSecond() {
    return 1;
  }
}

不会让它变得比它需要的更难,而且引入 PowerMock 往往会增加我不想处理的复杂性。 YMMV。祝你好运!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-09-25
    • 2012-05-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-02
    • 2017-10-08
    • 1970-01-01
    • 2013-02-26
    相关资源
    最近更新 更多