您不想在单元测试中实际连接到真实服务器。如果您想实际连接到真实服务器,这在技术上是一个集成测试。
由于您正在测试客户端代码,因此您应该使用单元测试,这样您就不需要连接到真实的服务器。相反,您可以使用模拟对象来模拟与服务器的连接。这真的很棒,因为您可以模拟使用真实服务器时难以实现的条件(例如会话中的连接失败等)。
使用 mock 进行单元测试也会使测试运行得更快,因为您不需要连接任何东西,因此没有 I/O 延迟。
由于您链接到另一个问题,我将使用该代码示例(为清楚起见,在此处重新粘贴)我创建了一个名为 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;
}
}
}
我将使用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 秒才能真正超时要快得多!