问题
“管理”被动视图的演示者订阅该视图中发生的事件(例如按钮单击),并且不直接将处理这些事件的方法公开为公共接口。我不喜欢将这些方法公开仅用于单元测试的想法,因为它闻起来像是暴露了内部实现细节。因此,调用该事件处理代码变得非常重要。
我的解决方案
视图模拟必须“拦截”事件订阅,然后使用相应的拦截侦听器来调用事件处理代码。我的实现包括一个实用程序类,它实现了 Mockito API 的 Answer 接口
private class ArgumentRetrievingAnswer<TArg> implements Answer {
private TArg _arg;
@Override
public Object answer(InvocationOnMock invocation) {
Object[] args = invocation.getArguments();
_arg = (TArg)args[0];
return null;
}
public TArg getArg() {
return _arg;
}
}
事件订阅的拦截方式如下
XyzView xyzView = mock(XyzView.class);
ArgumentRetrievingAnswer<OnEventListener> xyzViewTouchedListenerInterceptor =
new ArgumentRetrievingAnswer<OnEventListener>();
doAnswer(xyzViewTouchedListenerInterceptor)
.when(xyzView).addViewTouchedListener(any(OnEventListener.class));
创建 SUT 实例后...
XyzPresenter sut = new XyzPresenter(xyzView);
...我获得了听众
OnEventListener xyzViewTouchListener = xyzViewTouchedListenerInterceptor.getArg();
在“ Act ”部分我调用了监听器的事件处理方法
xyzViewTouchListener.onEvent();
问题
我对 Java 中的单元测试很陌生,所以我想知道是否有更优雅的方式来测试演示者代码。当前的“排列”部分相当臃肿,似乎在可读性方面并不出色。
编辑: 应乔纳森的要求添加简化的 SUT 代码。它说明演示者没有任何公共方法(构造函数除外),并订阅视图事件。
public interface XyzView {
void setInfoPanelCaptionText(String text);
void addViewInitializedListener(OnEventListener listener);
void addViewTouchedListener(OnEventListener listener);
}
public class XyzPresenter {
private XyzView _xyzView;
private OnEventListener _xyzViewTouchedListener = new OnEventListener() {
@Override
public void onEvent() {
handleXyzViewTouch();
}
};
public XyzPresenter(XyzView xyzView) {
_xyzView = xyzView;
_xyzView.addViewTouchedListener(_xyzViewTouchedListener);
}
private void handleXyzViewTouch() {
// event handling code
}
}