junit 使用stub进行粗粒度测试

发布时间 2023-04-02 15:51:34作者: 应晚星

测试背景:

1. 程序要以 http 连接到第三方的web服务器上。

2. 功能依赖于 其他人员开发的模块。。。但其他模块尚未完成,需要用仿造系统来替代。

通常有两种策略来生成模拟对象。stub技术和 mock objects

 

一、stub 简介

stub是一种机制,用来模拟真实代码  或者尚未完成的代码。

优点:

  1.  对所测试的代码,修改小。。。避免修改现有的复杂系统。

  2. 对粗粒度测试而言,就如同在子系统之间集成测试。

弊端:

  1. stub 比较复杂,难以编写。本身还需要调试

  2.因为stub复杂,所以可能很难维护。

  3. stub 不能用于细粒度测试。

 

二、示例

 要测试的方法, 是   WebClient.getContent(URL url)

从一个 URL 获取web内容信息。

public class WebClient{
    public String getContent(URL url){
    StringBuffer content = new StringBuffer();
        try{
            HttpURLConnection connection = (HttpURLConnection)url.openConnection();
            connection.setDoInput(true);
            InputStream is = connection.getInputStream();
            while(count=is.read(buffer)!=-1){
                content.appent(new Strign(buffer, 0, count);
            }
        }catch(IOException e){
            return null;
        }
        return content.toString();
    }
}

  

stub1:

   通过嵌入式web容器 jetty, 在本地启动一个web服务器。在 http://localhost:8080/testGetContentOK   返回 "It works";

    测试用例, 调用 WebClient.getContent("http://localhost:8080/testGetContentOK"),   断言返回的 文本是"It works".

回顾:stub必须保持简单,不要花费太多调试,维护的成本在 stub上。 

@Test
public void tegetGetContentOK() throws Exception{
    WebClient client = new WebClient();
    String result = client.getContent(new URL("http://localhost:8080/tegteGetContentOK"));
    
    assertEquals("It works", result);
}

 

stub2

替换 URL的处理器

public class TestWebClient1{
    @BeforeClass
    public static void SetUp(){
        TestWebClient1 t = new TestWebClient1();
        URL.setURLStreamHandlerFactory(t.new StubStreamHandlerFactory());
    }
    
    private class StubStreamHandlerFactory implements URLSteamHandlerFactory{
        public URLStreamHandler createURLStreamHandler(String protocol){
            return new StubHttpURLStreamHandler();
        }
    }
    private class StubHttpURLStreamHandler extends URLStreamHandler{
        protected URLConnection openConnection(URL url){
            throw new StubHttpURLConnection(url);
        }
    }
    
    @Test
    public void testGetContentOK(){
        WebClient client = new WebClient();
        String result = client.getContent(new URL("http://localhost"));
        assertEquals("It works", result);
    }    
}

 

在测试前,替换了 URL 的处理器, setURLStreamHandlerFactory, 最后实现改为由  StubHttpURLConnection  实现处理url 。

public class StubHttpURLConnection extends HttpURLConnection{
    private boolean isInput = true;
    protected StubHttpURLConnection(URL url){
        super(url);
    }
    public InputStream getInputStream() throws IOException{
        ByteArrayInputStream bais = new ByteArrayInputStream(new String("It works").getBytes());
        return bais;
    }
    public void disconnect(){}
    public void connect() throws IOException{}
}