如何模拟私有静态内部类?

时间:2016-05-30 20:02:33

标签: java unit-testing mocking

我有一个像

这样的课程
public class Enclosing {

   public String methodA() {
     Inner.getContext();
     ......
   }

   private static class Inner{
     // some context init
     public static Context getContext() {
       .....
     }
   }
}

现在我想测试methodA而不调用真正的Inner.getContext()。我一直在搜索,但找不到有效的解决方案。我正在使用Java 8.请帮助我吗?非常感谢

3 个答案:

答案 0 :(得分:2)

您可以应用扩展和覆盖技术,这是它的工作原理。

鉴于此代码:

public class Enclosing {

   public String methodA() {
     Inner.getContext();
     ......
   }

您可以将Inner.getContext()来电转移到protected方法:

public class Enclosing {

   public String methodA() {
     getContext();
     ......
   }

   protected void getContext() {
     Inner.getContext();
     ......
   }

然后在您的测试用例中,您可以扩展封闭类,并覆盖protected方法以随意执行任何操作:

@Test
public void test_something() {
    Enclosing enclosing = new Enclosing() {
        @Override
        protected void getContext() {
            // do what you need here
        }
    };

    // your test code on enclosing where you control getContext
}

答案 1 :(得分:1)

作为@janos'答案的替代方案,你可以注入一个策略(基本上,“偏好于继承的组合”方法):

interface ContextStrategy {
  void getContext();
}

然后将此实例注入Enclosing的构造函数:

class Enclosing {
  private final ContextStrategy ctxStrategy;

  Enclosing(ContextStrategy ctxStrategy) {
    this.ctxStrategy = ctxStrategy;
  }

  String methodA() {
    ctxStrategy.getContext();
    // ...
  }
}

然后为生产案例实现此接口,作为Enclosing中的嵌套类:

static class ContextStrategyImpl implements ContextStrategy {
  @Override public void getContext() {
    Inner.getContext();
  }
}

并为您的模拟案例实现替代版本。

答案 2 :(得分:0)

你应该模拟一个private类(无论它是像这里的嵌套类还是实际的内部类)。

相反,如果确实需要,则仅模拟Context类型(否则,使用真正的Context对象)。例如,下面显示了这样的测试,使用JMockit库:

@Test
public void mockingTheContext(@Mocked Context anyContext) {
    new Expectations() {{
      // record any method call results expected from "anyContext"
    }};

    new Enclosing().methodA();

    new Verifications() {{
      // verify calls to "anyContext", if applicable
    }};
}

在上面的测试中,在嵌套类中创建Context的事实是无关紧要的。通常,应始终避免使用模拟private方法或类,因为它们只是实现细节。