【问题标题】:Mock Access to Outer Object From Local Inner Class从本地内部类模拟访问外部对象
【发布时间】:2019-04-11 08:43:50
【问题描述】:

我有一个在其方法之一中具有本地内部类的类:

public class Outer {
    String hello = "hello";

    public void myMethod() {

        class Inner {
            public void myInnerMethod() {
                System.out.println(hello);         
            }
        }

        [...really slow routine...]

        (new Inner()).myInnerMethod();
    }
}

我想测试myInnerMethod()。所以我使用反射来实例化本地内部类并在其上调用myInnerMethod()

public void test() {
    Object inner = Class.forName("Outer$Inner").newInstance();
    inner.getClass().getDeclaredMethod("myInnerMethod").invoke(inner); // hello will be null
}

但是当myInnerMethod()访问hello时,在Outer类的范围内,是null

有没有办法模拟或以其他方式向myInnerMethod()打招呼?

我知道我可以通过提取内部类来重构我的代码,或者只测试 Outer 的公共方法。但是还有办法吗?

【问题讨论】:

  • 好吧,无论如何你都需要一个Outer 的实例来访问hello,那么为什么不在你的测试中也创建一个Outer 的实例呢?顺便说一句,我怀疑你得到 NPE,因为 hello 为空,但你可能得到它,因为对 Outer 的引用为空(你可以认为对 hello 的访问实际上是 Outer.this.hello)。
  • 显示完整的 myMethod 实现.. Inner 如何实例化然后调用
  • 感谢@Thomas。我修改了代码中的注释行
  • 完成@MaciejKowalski

标签: java unit-testing junit mockito


【解决方案1】:

在能够验证内部行为之前,您需要进行一些小的重构:

1) 创建一个包级方法,其中包含从myInnerMEthod 中调用的代码:

public class Outer {
    String hello = "hello";

    public void myMethod() {

        class Inner {
            public void myInnerMethod() {
                Outer.this.printHello(hello);    // !!! change here     
            }
        }

        [...really slow routine...]

        (new Inner()).myInnerMethod();
    }

    void printHello(String hello){/* */}   // !! add this
}

2) 监视 Outer 类并验证 printHello 是否已使用 hello 实例变量调用:

public void test() {
    // Arrange
    Outer outerSpy = spy(new Outer());
    doNothing().when(outerSpy).printHello(anyString()); // optional

    // Act
    outer.myMethod();

    // Assert
    verify(outerSpy).printHello("hello");
}

【讨论】:

  • 此解决方案测试外部方法并将逻辑移动到外部类。这不是我理想中想要的。
  • 您不应该在自身上测试内部类行为,因为它等同于私有方法的单元测试行为。你不应该那样做。测试 SUT 的公共行为,而不是其内部运作
  • 进一步查看我的实际代码,我意识到我真正想要测试的逻辑最好放在外部类的新方法中。所以你的解决方案非常有意义。
  • 太棒了。很高兴它帮助了你
猜你喜欢
  • 2021-08-18
  • 1970-01-01
  • 2021-06-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-11
  • 2021-07-24
  • 2011-01-02
相关资源
最近更新 更多