一个JUNIT实例-控制器框架

目标:设计一个controller组件

设计接口:

Controller接受Request,分发给RequestHandler,并返回Response对象,有了这样一些描述,就可以编写一些初步的接口。

public interface Request {

String getName();

}

public interface Response {

}

public interface RequestHandler {

Response process(Request request) throws Exception;

}

public interface Controller {

Response processRequest(Request request);

//注册一个处理器(反转控制模式:不要呼叫我们,我们会呼叫你)

void addHandler(Request request,RequestHandler requestHandler);

}

Controller用到的设计模式:inversion of control

向Controller注册一个处理器是反转控制(依赖注入)模式的例子,“不要呼叫我们,我们会呼叫你”。对象(requestHandler)注册成事件的处理器。当事件发生时(processRequest),注册的对象的钩子方法(process)就会被调用。Inversion of control使得框架可以管理事件的声明周期,让开发者可以为框架事件插入自定义的处理器。

初步实现Controller类

public class DefaultController implements Controller{

 

private Map requestHandlers = new HashMap();//请求处理器的注册表

 

/**

* 为指定的请求获取RequestHandler

*/

public RequestHandler getHandler(Request request){

 

//如果requestHandler没有注册,则抛出异常

if(!requestHandlers.containsKey(request.getName())){

String message = "can't find handler for request name" + "["+request.getName() + "]";

throw new RuntimeException(message);

}

//返回一个合适的处理器

return (RequestHandler)requestHandlers.get(request.getName()); }

public void addHandler(Request request, RequestHandler requestHandler) {

 

//检查处理器的名字是否已经注册过了

if(requestHandlers.containsKey(request.getName())){

throw new RuntimeException("a request handler has already been registered for request name"+ "[" + request.getName() + "]");

}

else{

requestHandlers.put(request.getName(), requestHandler);

}

}

/**

* 核心方法:把请求分派至合适的处理器,并且把处理器的response传递给调用者

*/

public Response processRequest(Request request) {

Response response;

try{

//路由请求

response = getHandler(request).process(request);

 

}catch(Exception exception){

//错误处理

response = new ErrorResponse(request,exception);

}

return response;

}

}

测试DefaultController

单元测试的要点在于,一次只测试一个对象。为了创建一个单元测试,你需要两种类型的对象:你要测试的领域对象(DefaultController)和同被测试的对象交互的测试对象(Request,Response,RequestHandler)。

测试类的放置

可以做为共有类放在PACKAGE中

作为单元测试的内部类。(更适合TDD模式开发,测试先行,再编写代码)

以下就是经过改进的单元测试类

public class TestDefaultController extends TestCase {

private DefaultController controller;

private Request request;

private RequestHandler handler;

private Response response;

 

public TestDefaultController(String name) {

super(name);

}

protected void setUp() throws Exception {

controller = new DefaultController();

request = new TestRequest();

handler = new TestHandler();

controller.addHandler(request, handler);

}

protected void tearDown() throws Exception {

}

//作为内部类的测试类

private class TestRequest implements Request{

 

private static final String DEFAULT_NAME = "test";

private String name;

 

public TestRequest(String name){

this.name = name;

}

public TestRequest(){

this(DEFAULT_NAME);

}

public String getName(){

return name;

}

}

 

//作为内部类的测试类

private class TestHandler implements RequestHandler{

 

public Response process(Request request) throws Exception {

return new TestResponse();

}

}

 

//作为内部类的测试类

private class TestResponse implements Response{ }

 

//用于异常情况的RequestHandler

private class TestExceptionHandler implements RequestHandler{

public Response process(Request request) throws Exception {

throw new Exception("error processing request");

}

}

 

//测试注册

public void testAddHandler(){

RequestHandler handler2 = controller.getHandler(request);

assertSame(handler2,handler);

}

 

//测试请求处理

public void testProcessRequest(){

Response response = controller.processRequest(request);

assertNotNull("Must not return a null response",response);

assertEquals(TestResponse.class,response.getClass());//?????

}

 

//模拟异常条件

public void testProcessRequestAnswersErrorResponse(){

request = new TestRequest("testError");

TestExceptionHandler handler = new TestExceptionHandler();

controller.addHandler(request, handler);

response = controller.processRequest(request);

assertNotNull("must not return a null response",response);

assertEquals( ErrorResponse.class,response.getClass());

}

 

//测试抛出异常的方法

public void testGetHandlerNotDefined(){

request = new TestRequest("testNotDefined");

try{

controller.getHandler(request);

fail("An exception should be raised if the requested handler has not been registered" );

}

catch(RuntimeException expected){

assertTrue(true);

}

}

}

可以总结出测试异常的模式:

1. 插入应当抛出异常的语句

2. 在它后面加上fail语句(以防万一没有抛出异常)

3. 捕捉预期的异常,把异常起名为expected。这样就容易看出这个异常是预期的。

4. 一切正常。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值