【JUnit实战】为应用程序Controller设计单元测试

在本章中,我们为一个简单但完整的应用程序controller创建了一个测试用例。测试用例并不是测试单个的组件,而是检验多个组例,如何一起工作。我们从一个可以用于任何类的简单测试用例开始.然后把新的测试逐个添加到测试用例中,直到所有初始的组件都被测试到。由于断言变得越来越复杂、因此我们通过Hamcrest匹配器找到了一种简化断言的方法。我们预期这个包会日益增长,所以我们为测试类创建了另一个源代码目录。因为测试源代码和领域源代码的目录都位于同一个包中,所以我们仍然可以测试受保护成员和默认的包成员。

1.被测部分:Controller模式

1.1 Controller简介

一般而言, Controller可以处理以下事务
- 接受请求
- 根据请求执行任意常用极端
- 选择 一个合适的请求处理器
- 路由请求,以便处理器可以执行相关的业务逻辑
- 可能提供一个顶层处理器来处理错误和异常

1.2 设计接口

Controller模式中涉及四个角色:
- Request
- Response
- RequestHandler
- Controller

Controller接受一个Request,分发给一个RequestHandler,并返回一个Response对象。

//首先,定义一个 Request 接口,这个接口只有一个返问请求的唯一名称的getName方法
public interface Request{
    String getName();
}
//其次指定一个空接口。要开始编写代码,你只需要返回一个 Response对象即可。Response 对象所封装的是你可以稍后处理的内容。
public interface Response{

}
//接下来,定义一个能够处理 Request 并返回 Response 的 RequestHandle,RequestHandle是一个辅助组件,被设计用来处理大部分的“肮脏工作”。它可以调用各种类,这些类可能抛出任意类型的异常。Exception就是由process万法抛出的。
public interface RequestHandler{
    Response procees(Request request) throws Exception;
}
//定义一个顶层方法来处理收到的请求。在接受请求之后, controller将请求分发给相应的RequestHandler 。
public interface Controller{
    Response process(Request request);
    //add Handler 方法允许你扩展Controller,而无须修改 Java原代码。
    void addHandler(Request request,RequestHandler requestHandler)
}

controller的目的是处理一个请求并返回一个响应。但是,在你处理一个请求之前,设计要求添加一个RequestHandler来做这个处理。

package com.JUnittTest.mastery;

import java.util.HashMap;
import java.util.Map;


public class DefaultController {
   
   
//  请求处理器注册表,对每一个request注册对应的requestHandler
    private Map requestHandlers=new HashMap();
//  声明一个受保护的方法,为接受的请求获取RequestHandler
    protected RequestHandler getHandler(Request request){
        if(!this.requestHandlers.containsKey(request.getName())){
            String message="Cannot find handler for request name "+"["+request.getName()+"]";
            throw new RuntimeException(message);
        }
//      向调用者返回相应的requestHandler
        return (RequestHandler)this.requestHandlers.get(request.getName());
    }

//  是Controller类的核心,把response分派给相应的requestHandler,并传回requestHandler的response
    public Response processRequest(Request request){
        Response response;
        try {
//          getHandler(request)返回一个RequestHandler接口类型的对象
//          RequestHandler接口定义了process(request)方法,返回一个response对象
            response=getHandler(request).process(request);
        } catch (Exception exception) {
            response=new ErrorResponse(request,exception);
        }
        return response;
    }
//  检查requestHandler是否已经被注册
    public void addHandler(Request request,RequestHandler requestHandler){
//      如果被注册了就抛出一个异常
        if(this.requestHandlers.containsKey(request.getName())){
            throw new RuntimeException("A request handler has "+"already been registered for request name "+"["+request.getName()+"]");
        }else{
            this.requestHandlers.put(request.getName(), requestHandler);
        }
    }
}

我们还需要额外再定义一个ErrorPesponse接口,不同于posponse接口,ErrorPesponse接口返回的是错误的posponse。

package com.JUnittTest.mastery;

public interface Response {
    String getName();
}

2. 设计单元测试

2.1 测试前部署 @Before @BeforeClass

@Before @After 注释方法会在每个@Test方法前后执行

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Before {
   
   
}

@BeforeClass @AfterClass 注释方法会在只会在所有@Test方法前后执行一次

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface BeforeClass {
   
   
}

从源代码分析,@Before @BeforeClass 注释非常简单,没有内部属性,只是起到对代码运行顺序的引导。(@After @AfterClass也是一样的)

一般在@BeforeClass @AfterClass注释方法中的代码完成测试环境的部署和拆除。
在@Before @After注释方法中的代

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值