舉個例子來說,你寫了一個方法,打算傳入一個java.net.URL, 希望可以用字串傳回該網址的文件內容:
package cc.openhome;
import java.io.*;
import java.net.URL;
public class HttpHelper {
    public String getContent(URL url) throws IOException {
        InputStream input = url.openStream();
        StringWriter writer = new StringWriter();
        byte[] data = new byte[2048];
        int length = -1;
        while((length = input.read(data)) != -1) {
            writer.write(new String(data, 0, length));
        }
        input.close();
        writer.close();
        return writer.toString();
    }
}
基本上,你可以建立一個HTTP伺服器,在上面放一些文件,然後建立URL實 例時指定資源網址,然後測試傳回的字串是否真的是伺服器上放置的資源。
如果你只是想測試程式的實作內容是否正確,而不是測試真正的HTTP連結是否正確,那麼以上的作法不僅麻煩,而且你連帶測試了你的伺服器正否正常,文 件網址是否正確等。
你真正想測試的是程式實作,但又得跟URL物 件互動,事實上,你可以傳入一個假的物件,該物件的實作儘量簡單,只傳回受測程 式必要的資料即可。仔細觀察你的程式實作中,實際上真正需要的,只是從URL物 件傳回一個InputStream而 已。
這個傳入的假物件稱為Dummy物件,以上例而言,最直覺的作 法,似乎是繼承URL,並 重新定義其openStream()方法,不過URL被定義為final而無法繼承,遵照URL的規範,你應該使用URL的 setURLStreamHandlerFactory()傳入一個URLStreamHandlerFactory的實作物件。例如:
package test.cc.openhome;
import static org.junit.Assert.*;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLStreamHandler;
import java.net.URLStreamHandlerFactory;
import org.junit.BeforeClass;
import org.junit.Test;
import cc.openhome.HttpHelper;
class DummyURLStreamHandlerFactory implements URLStreamHandlerFactory {
    public URLStreamHandler createURLStreamHandler(String protocol) {
        return new URLStreamHandler() {
            @Override
            protected URLConnection openConnection(URL u) 
                                         throws IOException {
                return new DummyURLConnection(u);
            }  
        };
    }
}
class DummyURLConnection extends HttpURLConnection {
    DummyURLConnection(URL u) {
        super(u);
    }
    @Override
    public InputStream getInputStream() throws IOException {
        return new ByteArrayInputStream(new String("success").getBytes());
    }
    @Override
    public void disconnect() {}
    @Override
    public boolean usingProxy() {
        return false;
    }
    @Override
    public void connect() throws IOException {}
}
public class HttpHelperTest {
    @BeforeClass
    public static void setUp() {
        URL.setURLStreamHandlerFactory(new DummyURLStreamHandlerFactory());
    }
    
    @Test
    public void testGetContent() throws Exception {
        HttpHelper helper = new HttpHelper();
        String expected = "success";
        String result = helper.getContent(new URL("http://localhost"));
        assertEquals(expected, result);
    }
}
簡單地說,在底層,URL 會呼叫一個URLConnection的實作,並呼叫其getInputStream()取得InputStream實例,在上頭最後實作了 DummyURLConnection,但僅簡單的重新定義了getInputStream(),其它什麼作沒實作,也沒有真正開 啟HTTP,這就是Dummy物件這個名稱的由來,因為它通常很 簡單,簡單到沒什麼動作與狀態,只傳回某個結果。
Dummy物件是模擬程式與現在資源互動的一種方式,由於其夠簡單,所以較容易實作,可以讓你將目標集中在真正想測試的程式上,但因為太簡單,無法反 映真正的資源或環境,如果你希望連同環境互動一同測試,也就是所謂的整合測試 (Integration test),那就不適用Dummy物件的策略。

