如何测试调用私有方法的匿名内部类

时间:2010-07-16 07:26:00

标签: java unit-testing testing junit

我们有一堆类从服务器侦听事件然后响应它们。例如:

class EventManager {
    private Set<Event> cache = new HashSet<Event>();

    private EventListener eventListener = new EventListener() {
        void onEvent(Event e) {
          if (e instanceof MyEvent || e instanceof YourEvent) {
            handleEvent(e);
          }  
        }
    }

    public EventManager(ServerCommunication serverComm) {
        serverComm.addListener(eventListener);
    }

    private handleEvent(Event e) {
        // handle the event...
        // ...
        cache.add(cache);
        // ...
    }
}

这是我们正在做的事情的一个组成例子。以下是我看到的问题:

  1. 我想测试handleEvent,以确保它正在做它应该做的事情,但我不能,因为它是私有的。
  2. 我还想检查是否有东西被添加到缓存中,但这似乎也很困难,因为缓存是私有成员,我不想添加一个不必要的getter方法。
  3. 我还想测试匿名类的onEvent方法中的代码。
  4. 现在,我所做的是将所有逻辑从匿名类移到handleEvent方法,并且我将handleEvent包设为私有(我的单元测试在同一个包中)。我不是在检查缓存的内容,尽管我想。

    有没有人对更易于测试的更好设计有任何建议?

5 个答案:

答案 0 :(得分:3)

我可能会提取一个EventCache组件。您可以使用实现计算缓存事件或记录任何感兴趣的内容来替换此测试。

我可能不会改变handleEvent的可见性。您可以实现一个只从测试用例中引发事件的ServerCommunication。

答案 1 :(得分:2)

嗯,这里有两种方法:黑盒子和白盒子。

黑盒测试表明您应该只测试公开可见的更改。这种方法是否有任何可观察到的影响? (有些事情没有 - 缓存是一个明显的例子,它们可以提高性能,但可能会看不见。)如果是这样,请测试一下。如果没有,请测试它没有否定效果 - 这可能只是加强其他测试。

白盒测试表明,为了测试,可能会添加一个包级别的方法,例如

Cache getCacheForTesting()

通过在名称中加入“for testing”,您可以明白每个人都不应该从生产代码中调用它。您可以使用注释来指示相同的内容,甚至可能有一些构建规则,以确保生产中没有任何内容调用这样的方法。

这最终会变得更脆弱 - 与实现更紧密相关 - 但它确实使得更容易彻底地测试代码,IMO。就我个人而言,我在单机测试的白盒测试方面犯了错误,而集成测试肯定是更黑盒子。其他人对测试公共API更加教条。

答案 2 :(得分:1)

我假设你的EventManager是一个单例,或者你可以访问你正在测试的类的特定实例。

1 - 我想你可以向你的班级发送活动。你的方法是私有的,没有其他人可以调用它,然后发送一个事件就足够了。

2 - 如果你真的需要,可以通过反射访问它。您的测试将取决于特定的实现。

3 - 实际上你想测试什么?如果要确保调用此方法,可以通过反射将EventListener替换为另一个EventListener对象(并最终从新侦听器调用第一个侦听器的onEvent方法)。但是你的问题似乎更多是关于代码覆盖而不是实际的单元测试。

答案 3 :(得分:1)

有时候,当遇到我想要测试的私有方法时......他们只是尖叫为另一个对象上的公共方法。

如果您认为HandleEvent值得单独测试(而不是通过onEvent处理),一种方法是将HandleEvent公开为新/不同对象的公共方法。

答案 4 :(得分:0)

利用这个机会将代码分解为更小的更集中(默认访问)类。测试只是代码的另一个客户端。

请注意,匿名内部类'onEvent方法实际上是可访问的,因此调用它应该不是问题。