有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何设置Zk会话(org.zkoss.Zk.ui),以便对扩展GenericForwardComposer的控制器类进行单元测试

我正在尝试对一个现有的ZK控制器进行单元测试,我想在对控制器进行单元测试时,找到一种处理如下调用的方法

Sessions.getCurrent().setAttribute("from", from.getValue());

我很乐意替换有问题的代码,或者为单元测试找到解决方法。我的目标是通过处理NullPointerException来实现可测试性

我的测试很简单(这是个不错的起点……)

    @Test
    public void zkControllerDoesMockingInitialisedSuccessfully() throws Exception {

    T2TripBigDaoInterface tripBigDao = createMock(T2TripBigDao.class);
    ZkFieldValidator fieldValidator = createMock(ZkTextFieldValidator.class);
    FieldRangeValidator rangeValidator = createMock(DefaultFieldRangeValidator.class);

    TripController controller = new TripController(tripBigDao, fieldValidator, rangeValidator);


    replay(tripBigDao, fieldValidator, rangeValidator);

    controller.onClick$getTrips(new Event("getTrips"));

    verify(tripBigDao, fieldValidator, rangeValidator);

    // Test purpose: Just get a unit test of the controller running to start with....
}


控制器的摘录:
public class TripController extends GenericForwardComposer {

....

   public void onClick$getTrips(Event event) throws Exception {
       Sessions.getCurrent().setAttribute("from", from.getValue());
       Sessions.getCurrent().setAttribute("to", to.getValue());

       ....
   }
....


堆栈跟踪的提取:
java.lang.NullPointerException
at com.t2.webservice.controller.alert.TripController.onClick$getTrips(TripController.java:72)
at com.t2.webservice.controller.alert.TripControllerTest.zkControllerDoesMockingInitialisedSuccessfully(TripControllerTest.java:45)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

共 (1) 个答案

  1. # 1 楼答案

    这是我最不喜欢ZK的地方之一:它们对单例的使用以及对可测试性的影响

    我最终要做的是从我的控制器中删除对它们的单例(SessionsExecutionsSelectors)的任何引用。在正常操作中,这些单件可以使用,但在测试中,它们可以被模拟出来

    你怎么做取决于你,我还没有找到我喜欢的模式
    这里有一个想法

    public class TripController extends GenericForwardComposer {
    
        private final TripSessionManager tripSessionManager;
    
        public TripController() {
            // ZK calls the default constructor
            this(new ZKTripSessionManager());
        }
    
        protected TripController(TripSessionManager tripSessionManager) {
            this.tripSessionManager = tripSessionManager;
        }
    
        public void onClick$getTrips(Event event) throws Exception {
            tripSessionManager.setTo(to.getValue());
            tripSessionManager.setFrom(from.getValue());
        }
    
    }
    

    你的TripSessionManager会是这样的

    public interface TripSessionManager {
    
        void setTo(String to);
    
        void setFrom(String from);
    
    }
    

    默认的ZK实现依赖于Sessions单例

    public ZKTripSessionManager implements TripSessionManager {
    
        public void setTo(String to) {
            setAttribute("to", to);
        }
    
        public void setFrom(String from) {
            setAttribute("from", from);
        }
    
        private void setAttribute(String name, String value) {
            // only valid if called in a ZK managed thread
            Sessions.getCurrent().setAttribute(name, value);
        }
    
    }
    

    通过抽象出实现,您可以使用模拟TripSessionManager测试控制器

    @Test
    public void test() {
        TripSessionManager mockTripSessionManager = mock(TripSessionManager);
        when(mockTripSessionManager.setTo(anyString()).thenAnswer(...);
        when(mockTripSessionManager.setFrom(anyString()).thenAnswer(...);
        TripController controller = new TripController(mockTripSessionManager);
    }
    

    您还可以想象使用Spring或Guice等依赖项注入框架管理这些新依赖项的不同方式(例如:避免new ZKTripSessionManager()