java 模拟 HTTP 客户端请求的 HTTP 服务器超时
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/25495773/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Simulate HTTP server time out for HTTP client request
提问by user3443883
In reference to: HttpURLConnection timeout question
参考: HttpURLConnection timeout question
-> Any idea on how to automate the unit test case for the above?
-> 关于如何自动化上述单元测试用例的任何想法?
More specifically, if the HTTP client has set 5 seconds as its timeout, I want the server to send the response after 10 seconds. This would ensure my client would fail due to time out and thus automating this scenario.
更具体地说,如果 HTTP 客户端将其超时设置为 5 秒,我希望服务器在 10 秒后发送响应。这将确保我的客户端会因超时而失败,从而使这种情况自动化。
I would appreciate the psuedo code for the server side (any light weight http server such as jetty or any other is fine).
我很感激服务器端的伪代码(任何轻量级的 http 服务器,如码头或任何其他服务器都可以)。
回答by dkatzel
You don't want to actually connect to a real server in a unittest. If you want to actually connect to a real server, that is technically an integration test.
您不想在单元测试中实际连接到真实服务器。如果您想真正连接到真正的服务器,这在技术上是一个集成测试。
Since you are testing the client code, you should use a unit test so you don't need to connect to a real server. Instead you can use mock objects to simulate a connection to a server. This is really great because you can simulate conditions that would be hard to achieve if you used a real server (like the connection failing in the middle of a session etc).
由于您正在测试客户端代码,因此您应该使用单元测试,这样您就不需要连接到真正的服务器。相反,您可以使用模拟对象来模拟与服务器的连接。这真的很棒,因为您可以模拟使用真实服务器时难以实现的条件(例如连接在会话中间失败等)。
Unit testing with mocks will also make the tests run faster since you don't need to connect to anything so there is no I/O delay.
使用模拟进行单元测试也将使测试运行得更快,因为您不需要连接到任何东西,因此没有 I/O 延迟。
Since you linked to another question, I will use that code example (repasted here for clarity) I made a class called MyClass
with a method foo()
that connects to the URL and returns true or false if the connection succeeded. As the linked question does:
由于您链接到另一个问题,我将使用该代码示例(为了清晰起见,在此处重新粘贴)我创建了一个MyClass
使用foo()
连接到 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;
}
}
}
I will use Mockitoto make the mock objects since that is one of the more popular mock object libraries. Also since the code creates a new URL object in the foo method (which isn't the best design) I will use the PowerMocklibrary which can intercept calls to new
. In a real production code, I recommend using dependency injection or at least method extraction for creating the URL
object to a factory method so you can override it to ease testing. But since I am keeping with your example, I won't change anything.
我将使用Mockito来制作模拟对象,因为它是比较流行的模拟对象库之一。此外,由于代码在 foo 方法中创建了一个新的 URL 对象(这不是最好的设计),我将使用PowerMock库,它可以拦截对new
. 在实际的生产代码中,我建议使用依赖注入或至少方法提取来创建URL
工厂方法的对象,以便您可以覆盖它以简化测试。但既然我坚持你的例子,我不会改变任何东西。
Here is the test code using Mockito and Powermock to test timeouts:
这是使用 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);
}
}
This test runs in less than a second which is much faster than having to actually wait for over 5 seconds for a real timeout!
此测试在不到一秒的时间内运行,这比实际等待超过 5 秒才能真正超时要快得多!