In reference to: 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.
I would appreciate the psuedo code for the server side (any light weight http server such as jetty or any other is fine).
You don't want to actually connect to a real server in a unit test. 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.
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:
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 Mockito to 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 PowerMock library 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.
Here is the test code using Mockito and Powermock to test timeouts:
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!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With