0

我正在尝试对现有的 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)
4

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);

}

使用依赖Sessions单例的默认 ZK 实现..

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);
}

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

于 2013-08-04T21:12:12.107 回答