簡體   English   中英

模擬HTTP客戶端請求的HTTP服務器超時

[英]Simulate HTTP server time out for HTTP client request

參考: HttpURLConnection超時問題

- >關於如何自動化上述單元測試用例的任何想法?

更具體地說,如果HTTP客戶端將超時設置為5秒,我希望服務器在10秒后發送響應。 這將確保我的客戶端因超時而失敗,從而自動化此方案。

我會很感激服務器端的偽代碼(任何輕量級的http服務器,如jetty或任何其他很好)。

您不希望在單元測試中實際連接到真實服務器。 如果您想實際連接到真實服務器,那么從技術上講,這是一個集成測試。

由於您正在測試客戶端代碼,因此您應該使用單元測試,這樣您就不需要連接到真實服務器。 相反,您可以使用模擬對象來模擬與服務器的連接。 這真的很棒,因為你可以模擬如果使用真實服務器很難實現的條件(比如在會話中間連接失敗等)。

使用模擬進行單元測試也會使測試運行得更快,因為您不需要連接任何東西,因此沒有I / O延遲。

由於您鏈接到另一個問題,我將使用該代碼示例(為了清楚起見,這里重新編寫)我使用方法foo()創建了一個名為MyClass的類,該方法連接到URL並在連接成功時返回true或false。 正如相關問題所做的那樣:

public class MyClass {

private String url = "http://example.com";

public boolean foo(){
    try {
           HttpURLConnection.setFollowRedirects(false);
           HttpURLConnection con = (HttpURLConnection) new URL(url).openConnection();
           con.setRequestMethod("HEAD");

           con.setConnectTimeout(5000); //set timeout to 5 seconds

           return (con.getResponseCode() == HttpURLConnection.HTTP_OK);
        } catch (java.net.SocketTimeoutException e) {
           return false;
        } catch (java.io.IOException e) {
           return false;
        }

    }
}

我將使用Mockito來制作模擬對象,因為這是一個比較流行的模擬對象庫。 此外,由於代碼在foo方法中創建了一個新的URL對象(這不是最好的設計),我將使用PowerMock庫來攔截對new調用。 在實際的生產代碼中,我建議使用依賴注入或至少方法提取來創建工廠方法的URL對象,以便您可以覆蓋它以簡化測試。 但既然我堅持你的榜樣,我就不會做任何改變。

以下是使用Mockito和Powermock測試超時的測試代碼:

import java.net.HttpURLConnection;
import java.net.SocketTimeoutException;    
import java.net.URL;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

import static org.junit.Assert.*;

@RunWith(PowerMockRunner.class)
//This tells powermock that we will modify MyClass.class in this test 
//- needed for changing the call to new URL
@PrepareForTest(MyClass.class) 
public class ConnectionTimeOutTest {

String url = "http://example.com";
@Test
public void timeout() throws Exception{
    //create a mock URL and mock HttpURLConnection objects
    //that will be our simulated server
    URL mockURL = PowerMockito.mock(URL.class);
    HttpURLConnection mockConnection = PowerMockito.mock(HttpURLConnection.class);

    //powermock will intercept our call to new URL( url) 
    //and return our mockURL object instead!
    PowerMockito.whenNew(URL.class).withArguments(url).thenReturn(mockURL);
    //This tells our mockURL class to return our mockConnection object when our client
    //calls the open connection method
    PowerMockito.when(mockURL.openConnection()).thenReturn(mockConnection);



    //this is our exception to throw to simulate a timeout
    SocketTimeoutException expectedException = new SocketTimeoutException();

    //tells our mockConnection to throw the timeout exception instead of returnig a response code
    PowerMockito.when(mockConnection.getResponseCode()).thenThrow(expectedException);

    //now we are ready to actually call the client code
    // cut = Class Under Test
    MyClass cut = new MyClass();

    //our code should catch the timeoutexception and return false
    assertFalse(cut.foo());

   // tells mockito to expect the given void methods calls
   //this will fail the test if the method wasn't called with these arguments
   //(for example, if you set the timeout to a different value)
    Mockito.verify(mockConnection).setRequestMethod("HEAD");
    Mockito.verify(mockConnection).setConnectTimeout(5000);

}
}

這個測試在不到一秒的時間內運行,這比實際超時實際等待超過5秒要快得多!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM