junit使用stub進行單元測試
阿新 • • 發佈:2019-01-12
stub是程式碼的一部分,我們要對某一方法做單元測試時,可能涉及到呼叫第三方web服務。假如當前該服務不存在或不可用咋辦?好辦,寫一段stub程式碼替代它。
stub 技術就是把某一部分程式碼與環境隔離起來(比如,通過替換 Web伺服器、檔案系統、資料庫等手段)從而進行單元測試的。
下面演示一個例子,利用jetty編寫相關的stub充當web伺服器,返回適當內容。
環境: idea + spring boot + jetty
關於jetty伺服器,對比tomcat更輕量級,可輕鬆嵌入java程式碼啟動它。
如何在專案中啟動一個jetty伺服器?
package com.lhy.junitkaifa.stubs; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.server.handler.ResourceHandler; /** * @author xusucheng * @create 2018-12-20 **/ public class JettySample { public static void main(String[] args) throws Exception { Server server = new Server( 8081 ); ContextHandler context = new ContextHandler(server,"/"); //預設為專案根目錄 context.setResourceBase("."); context.setHandler(new ResourceHandler()); server.setStopAtShutdown( true ); server.start(); } }
請求:http://localhost:8081
編寫一個獲取url內容的工具方法叫WebClient
package com.lhy.junitkaifa.stubs; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; /** * 讀取指定URL內容 * @author xusucheng * @create 2018-12-20 **/ 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(); byte[] buffer = new byte[2048]; int count; while ( -1 != ( count = is.read( buffer ) ) ) { content.append( new String( buffer, 0, count ) ); } } catch ( IOException e ) { return null; } return content.toString(); } public static void main(String[] args) throws Exception{ WebClient wc = new WebClient(); String content = wc.getContent(new URL("http://www.baidu.com/")); System.out.println(content); } }
編寫測試類TestWebClient
package com.lhy.junitkaifa.stubs; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.server.handler.HandlerList; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.util.ByteArrayISO8859Writer; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; import org.springframework.http.HttpHeaders; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.OutputStream; import java.net.URL; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; /** * @author xusucheng * @create 2018-12-20 **/ public class TestWebClient { private WebClient client = new WebClient(); private static final int PORT=8081; @BeforeClass public static void setUp() throws Exception{ System.out.println("====================Befor Class====================="); Server server = new Server(PORT); TestWebClient t = new TestWebClient(); ContextHandler contentOkContext = new ContextHandler(server,"/testGetContentOk"); contentOkContext.setHandler(t.new TestGetContentOkHandler()); ContextHandler contentErrorContext = new ContextHandler(server,"/testGetContentError"); contentErrorContext.setHandler(t.new TestGetContentServerErrorHandler()); ContextHandler contentNotFoundContext = new ContextHandler(server,"/testGetContentNotFound"); contentNotFoundContext.setHandler(t.new TestGetContentNotFoundHandler()); HandlerList handlers = new HandlerList(); handlers.setHandlers(new Handler[] { contentOkContext, contentErrorContext, contentNotFoundContext}); server.setHandler(handlers); server.setStopAtShutdown( true ); server.start(); } @Test public void testGetContentOk() throws Exception { String result = client.getContent( new URL( "http://localhost:"+PORT+"/testGetContentOk" ) ); assertEquals( "It works", result ); } @Test public void testGetContentError() throws Exception { String result = client.getContent( new URL( "http://localhost:"+PORT+"/testGetContentError/" ) ); assertNull( result ); } @Test public void testGetContentNotFound() throws Exception { String result = client.getContent( new URL( "http://localhost:"+PORT+"/testGetContentNotFound" ) ); assertNull( result ); } @AfterClass public static void tearDown() { // Do nothing becuase the Jetty server is configured // to stop at shutdown. System.out.println("====================After Class====================="); } /** * 正常請求處理器 */ private class TestGetContentOkHandler extends AbstractHandler { @Override protected void doStart() throws Exception { super.doStart(); } @Override public void setServer(Server server) { super.setServer(server); } @Override public void handle(String s, Request request, HttpServletRequest httpServletRequest, HttpServletResponse response) throws IOException, ServletException { System.out.println("======================TestGetContentOkHandler======================="); OutputStream out = response.getOutputStream(); ByteArrayISO8859Writer writer = new ByteArrayISO8859Writer(); writer.write( "It works" ); writer.flush(); response.setIntHeader( HttpHeaders.CONTENT_LENGTH, writer.size() ); writer.writeTo( out ); out.flush(); request.setHandled(true); } } /** * 異常請求處理器 */ private class TestGetContentServerErrorHandler extends AbstractHandler { @Override public void handle(String s, Request request, HttpServletRequest httpServletRequest, HttpServletResponse response) throws IOException, ServletException { response.sendError( HttpServletResponse.SC_SERVICE_UNAVAILABLE ); } } /** * 404處理器 */ private class TestGetContentNotFoundHandler extends AbstractHandler { @Override public void handle(String s, Request request, HttpServletRequest httpServletRequest, HttpServletResponse response) throws IOException, ServletException { response.sendError( HttpServletResponse.SC_NOT_FOUND ); } } }
直接執行該類,結果為: