模拟静态方法内部的静态方法

Mock a static method that's inside a static method

我有一个调用另一个静态方法 (bar) 的静态方法 (foo)。我想在我的测试中模拟 bar 的响应。这可以用 PowerMockito 或其他工具实现吗?我能找到的唯一结果是在非静态方法中模拟静态。

public class SomeClass {
   static List<String> foo() {
      ...
      int barResult = bar();
      ...
   }

   static int bar() {
      // make a database call
      return DAO.getDao().runQuery();
   }
}

我的测试会这样称呼它:

@RunWith(PowerMockRunner.class)
public class SomeClassTest {

   @PrepareForTest(SomeClass.class)
   @Test
   public void fooTest() {
      List<String> actualResult = SomeClass.foo();
      assertTrue(...);
   }
}

我必须模拟 bar 的内部结构吗?所以嘲笑 DAO?

你不能那样做。

只有 PowerMock 允许您模拟静态方法。但这通过 "erasing" class 中的所有静态事物起作用,这些事物得到 "prepared" 以供 PowerMock 测试。

如果您谈论的是普通方法,您可能会选择 Mockito 间谍,因为它们允许部分模拟。

并且仅作记录:简单地避免使用静态,因为使用它会导致 "hard to test" 代码。

换句话说:与其使用又大又丑的 powermock 锤子来解决 "fix" 你的设计问题......不如考虑修复你损坏的设计,从而完全避免对 PowerMock 的需求!

郑重声明:是的,您可以通过模拟 DAO class 上的静态调用来解决您的问题(然后您可以控制 bar() 间接执行的操作。但同样:这只是意味着将 "I tested it" 标签放在应该改写的代码上。

你可以这样做:

@RunWith(PowerMockRunner.class)
@PrepareForTest({SomeClass.class, DAO.class})
public class SomeClassTest {

   @Test
   public void fooTest() {
      PowerMockito.mockStatic(DAO.class);
      Mockito.when(DAO.getDao().runQuery()).return(..);
      List<String> actualResult = SomeClass.foo();
      assertTrue(...);
   }
}