DefaultRequestDirectorTest.java revision 0a362c553c20d1213806246a5dd5488218444eb1
1package com.xtremelabs.robolectric.shadows;
2
3import com.xtremelabs.robolectric.Robolectric;
4import com.xtremelabs.robolectric.WithTestDefaultsRunner;
5import com.xtremelabs.robolectric.tester.org.apache.http.FakeHttpLayer;
6import com.xtremelabs.robolectric.tester.org.apache.http.RequestMatcher;
7import com.xtremelabs.robolectric.tester.org.apache.http.TestHttpResponse;
8import com.xtremelabs.robolectric.util.Strings;
9import junit.framework.Assert;
10import org.apache.http.HttpRequest;
11import org.apache.http.HttpResponse;
12import org.apache.http.client.methods.HttpGet;
13import org.apache.http.client.methods.HttpPost;
14import org.apache.http.client.methods.HttpUriRequest;
15import org.apache.http.conn.ConnectTimeoutException;
16import org.apache.http.conn.ConnectionKeepAliveStrategy;
17import org.apache.http.impl.client.BasicResponseHandler;
18import org.apache.http.impl.client.DefaultHttpClient;
19import org.apache.http.impl.client.DefaultRequestDirector;
20import org.apache.http.message.BasicHeader;
21import org.apache.http.params.HttpConnectionParams;
22import org.apache.http.params.HttpParams;
23import org.apache.http.protocol.HttpContext;
24import org.junit.After;
25import org.junit.Before;
26import org.junit.Test;
27import org.junit.runner.RunWith;
28
29import java.io.IOException;
30import java.io.InputStream;
31import java.net.URI;
32
33import static com.xtremelabs.robolectric.Robolectric.shadowOf;
34import static org.hamcrest.core.IsEqual.equalTo;
35import static org.junit.Assert.*;
36
37@RunWith(WithTestDefaultsRunner.class)
38public class DefaultRequestDirectorTest {
39    private DefaultRequestDirector requestDirector;
40    private ConnectionKeepAliveStrategy connectionKeepAliveStrategy;
41
42    @Before
43    public void setUp_EnsureStaticStateIsReset() {
44        FakeHttpLayer fakeHttpLayer = Robolectric.getFakeHttpLayer();
45        assertFalse(fakeHttpLayer.hasPendingResponses());
46        assertFalse(fakeHttpLayer.hasRequestInfos());
47        assertFalse(fakeHttpLayer.hasResponseRules());
48        assertNull(fakeHttpLayer.getDefaultResponse());
49
50        connectionKeepAliveStrategy = new ConnectionKeepAliveStrategy() {
51            @Override public long getKeepAliveDuration(HttpResponse httpResponse, HttpContext httpContext) {
52                return 0;
53            }
54        };
55        requestDirector = new DefaultRequestDirector(null, null, null, connectionKeepAliveStrategy, null, null, null, null, null, null, null, null);
56    }
57
58    @After
59    public void tearDown_EnsureStaticStateIsReset() throws Exception {
60        Robolectric.addPendingHttpResponse(200, "a happy response body");
61    }
62
63    @Test
64    public void shouldGetHttpResponseFromExecute() throws Exception {
65        Robolectric.addPendingHttpResponse(new TestHttpResponse(200, "a happy response body"));
66        HttpResponse response = requestDirector.execute(null, new HttpGet("http://example.com"), null);
67
68        assertNotNull(response);
69        assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
70        assertThat(Strings.fromStream(response.getEntity().getContent()), equalTo("a happy response body"));
71    }
72
73    @Test
74    public void shouldPreferPendingResponses() throws Exception {
75        Robolectric.addPendingHttpResponse(new TestHttpResponse(200, "a happy response body"));
76
77        Robolectric.addHttpResponseRule(HttpGet.METHOD_NAME, "http://some.uri",
78                new TestHttpResponse(200, "a cheery response body"));
79
80        HttpResponse response = requestDirector.execute(null, new HttpGet("http://some.uri"), null);
81
82        assertNotNull(response);
83        assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
84        assertThat(Strings.fromStream(response.getEntity().getContent()), equalTo("a happy response body"));
85    }
86
87    @Test
88    public void shouldReturnRequestsByRule() throws Exception {
89        Robolectric.addHttpResponseRule(HttpGet.METHOD_NAME, "http://some.uri",
90                new TestHttpResponse(200, "a cheery response body"));
91
92        HttpResponse response = requestDirector.execute(null, new HttpGet("http://some.uri"), null);
93
94        assertNotNull(response);
95        assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
96        assertThat(Strings.fromStream(response.getEntity().getContent()), equalTo("a cheery response body"));
97    }
98
99    @Test
100    public void shouldReturnRequestsByRule_MatchingMethod() throws Exception {
101        Robolectric.setDefaultHttpResponse(404, "no such page");
102        Robolectric.addHttpResponseRule(HttpPost.METHOD_NAME, "http://some.uri",
103                new TestHttpResponse(200, "a cheery response body"));
104
105        HttpResponse response = requestDirector.execute(null, new HttpGet("http://some.uri"), null);
106
107        assertNotNull(response);
108        assertThat(response.getStatusLine().getStatusCode(), equalTo(404));
109    }
110
111    @Test
112    public void shouldReturnRequestsByRule_AnyMethod() throws Exception {
113        Robolectric.addHttpResponseRule("http://some.uri", new TestHttpResponse(200, "a cheery response body"));
114
115        HttpResponse getResponse = requestDirector.execute(null, new HttpGet("http://some.uri"), null);
116        assertNotNull(getResponse);
117        assertThat(getResponse.getStatusLine().getStatusCode(), equalTo(200));
118        assertThat(Strings.fromStream(getResponse.getEntity().getContent()), equalTo("a cheery response body"));
119
120        HttpResponse postResponse = requestDirector.execute(null, new HttpPost("http://some.uri"), null);
121        assertNotNull(postResponse);
122        assertThat(postResponse.getStatusLine().getStatusCode(), equalTo(200));
123        assertThat(Strings.fromStream(postResponse.getEntity().getContent()), equalTo("a cheery response body"));
124    }
125
126    @Test
127    public void shouldReturnRequestsByRule_KeepsTrackOfOpenContentStreams() throws Exception {
128        TestHttpResponse testHttpResponse = new TestHttpResponse(200, "a cheery response body");
129        Robolectric.addHttpResponseRule("http://some.uri", testHttpResponse);
130
131        assertThat(testHttpResponse.entityContentStreamsHaveBeenClosed(), equalTo(true));
132
133        HttpResponse getResponse = requestDirector.execute(null, new HttpGet("http://some.uri"), null);
134        InputStream getResponseStream = getResponse.getEntity().getContent();
135        assertThat(Strings.fromStream(getResponseStream), equalTo("a cheery response body"));
136        assertThat(testHttpResponse.entityContentStreamsHaveBeenClosed(), equalTo(false));
137
138        HttpResponse postResponse = requestDirector.execute(null, new HttpPost("http://some.uri"), null);
139        InputStream postResponseStream = postResponse.getEntity().getContent();
140        assertThat(Strings.fromStream(postResponseStream), equalTo("a cheery response body"));
141        assertThat(testHttpResponse.entityContentStreamsHaveBeenClosed(), equalTo(false));
142
143        getResponseStream.close();
144        assertThat(testHttpResponse.entityContentStreamsHaveBeenClosed(), equalTo(false));
145
146        postResponseStream.close();
147        assertThat(testHttpResponse.entityContentStreamsHaveBeenClosed(), equalTo(true));
148    }
149
150    @Test
151    public void shouldReturnRequestsByRule_WithTextResponse() throws Exception {
152        Robolectric.addHttpResponseRule("http://some.uri", "a cheery response body");
153
154        HttpResponse response = requestDirector.execute(null, new HttpGet("http://some.uri"), null);
155
156        assertNotNull(response);
157        assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
158        assertThat(Strings.fromStream(response.getEntity().getContent()), equalTo("a cheery response body"));
159    }
160
161    @Test
162    public void clearHttpResponseRules_shouldRemoveAllRules() throws Exception {
163        Robolectric.addHttpResponseRule("http://some.uri", "a cheery response body");
164        Robolectric.clearHttpResponseRules();
165        Robolectric.addHttpResponseRule("http://some.uri", "a gloomy response body");
166
167        HttpResponse response = requestDirector.execute(null, new HttpGet("http://some.uri"), null);
168
169        assertNotNull(response);
170        assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
171        assertThat(Strings.fromStream(response.getEntity().getContent()), equalTo("a gloomy response body"));
172    }
173
174    @Test
175    public void clearPendingHttpResponses() throws Exception {
176        Robolectric.addPendingHttpResponse(200, "earlier");
177        Robolectric.clearPendingHttpResponses();
178        Robolectric.addPendingHttpResponse(500, "later");
179
180        HttpResponse response = requestDirector.execute(null, new HttpGet("http://some.uri"), null);
181
182        assertNotNull(response);
183        assertThat(response.getStatusLine().getStatusCode(), equalTo(500));
184        assertThat(Strings.fromStream(response.getEntity().getContent()), equalTo("later"));
185    }
186
187    @Test
188    public void shouldReturnRequestsByRule_WithCustomRequestMatcher() throws Exception {
189        Robolectric.setDefaultHttpResponse(404, "no such page");
190
191        Robolectric.addHttpResponseRule(new RequestMatcher() {
192            @Override public boolean matches(HttpRequest request) {
193                return request.getRequestLine().getUri().equals("http://matching.uri");
194            }
195        }, new TestHttpResponse(200, "a cheery response body"));
196
197        HttpResponse response = requestDirector.execute(null, new HttpGet("http://matching.uri"), null);
198        assertNotNull(response);
199        assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
200        assertThat(Strings.fromStream(response.getEntity().getContent()), equalTo("a cheery response body"));
201
202        response = requestDirector.execute(null, new HttpGet("http://non-matching.uri"), null);
203        assertNotNull(response);
204        assertThat(response.getStatusLine().getStatusCode(), equalTo(404));
205        assertThat(Strings.fromStream(response.getEntity().getContent()), equalTo("no such page"));
206    }
207
208    @Test
209    public void shouldGetHttpResponseFromExecuteSimpleApi() throws Exception {
210        Robolectric.addPendingHttpResponse(200, "a happy response body");
211        HttpResponse response = requestDirector.execute(null, new HttpGet("http://example.com"), null);
212
213        assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
214        assertThat(Strings.fromStream(response.getEntity().getContent()), equalTo("a happy response body"));
215    }
216
217    @Test
218    public void shouldHandleMultipleInvocations() throws Exception {
219        Robolectric.addPendingHttpResponse(200, "a happy response body");
220        Robolectric.addPendingHttpResponse(201, "another happy response body");
221
222        HttpResponse response1 = requestDirector.execute(null, new HttpGet("http://example.com"), null);
223        HttpResponse response2 = requestDirector.execute(null, new HttpGet("www.example.com"), null);
224
225        assertThat(response1.getStatusLine().getStatusCode(), equalTo(200));
226        assertThat(Strings.fromStream(response1.getEntity().getContent()), equalTo("a happy response body"));
227
228        assertThat(response2.getStatusLine().getStatusCode(), equalTo(201));
229        assertThat(Strings.fromStream(response2.getEntity().getContent()), equalTo("another happy response body"));
230    }
231
232    @Test
233    public void shouldHandleMultipleInvocationsOfExecute() throws Exception {
234        Robolectric.addPendingHttpResponse(200, "a happy response body");
235        Robolectric.addPendingHttpResponse(201, "another happy response body");
236
237        requestDirector.execute(null, new HttpGet("http://example.com"), null);
238        requestDirector.execute(null, new HttpGet("www.example.com"), null);
239
240        HttpUriRequest request1 = (HttpUriRequest) Robolectric.getSentHttpRequest(0);
241        assertThat(request1.getMethod(), equalTo(HttpGet.METHOD_NAME));
242        assertThat(request1.getURI(), equalTo(URI.create("http://example.com")));
243
244        HttpUriRequest request2 = (HttpUriRequest) Robolectric.getSentHttpRequest(1);
245        assertThat(request2.getMethod(), equalTo(HttpGet.METHOD_NAME));
246        assertThat(request2.getURI(), equalTo(URI.create("www.example.com")));
247    }
248
249    @Test
250    public void shouldRejectUnexpectedCallsToExecute() throws Exception {
251        try {
252            requestDirector.execute(null, new HttpGet("http://example.com"), null);
253            fail();
254        } catch (RuntimeException expected) {
255            assertThat(expected.getMessage(), equalTo("Unexpected call to execute, no pending responses are available. See Robolectric.addPendingResponse(). Request was: GET http://example.com"));
256        }
257    }
258
259    @Test
260    public void shouldRecordExtendedRequestData() throws Exception {
261        Robolectric.addPendingHttpResponse(200, "a happy response body");
262        HttpGet httpGet = new HttpGet("http://example.com");
263        requestDirector.execute(null, httpGet, null);
264
265        assertSame(Robolectric.getSentHttpRequestInfo(0).getHttpRequest(), httpGet);
266        ConnectionKeepAliveStrategy strategy = shadowOf((DefaultRequestDirector) Robolectric.getSentHttpRequestInfo(0).getRequestDirector()).getConnectionKeepAliveStrategy();
267        assertSame(strategy, connectionKeepAliveStrategy);
268    }
269
270    @Test
271    public void shouldSupportBasicResponseHandlerHandleResponse() throws Exception {
272        Robolectric.addPendingHttpResponse(200, "OK", new BasicHeader("Content-Type", "text/plain"));
273
274        DefaultHttpClient client = new DefaultHttpClient();
275        HttpResponse response = client.execute(new HttpGet("http://www.nowhere.org"));
276
277        assertThat(((HttpUriRequest) Robolectric.getSentHttpRequest(0)).getURI(),
278                equalTo(URI.create("http://www.nowhere.org")));
279
280        Assert.assertNotNull(response);
281        String responseStr = new BasicResponseHandler().handleResponse(response);
282        Assert.assertEquals("OK", responseStr);
283    }
284
285    @Test
286    public void shouldFindLastRequestMade() throws Exception {
287        Robolectric.addPendingHttpResponse(200, "a happy response body");
288        Robolectric.addPendingHttpResponse(200, "a happy response body");
289        Robolectric.addPendingHttpResponse(200, "a happy response body");
290
291        DefaultHttpClient client = new DefaultHttpClient();
292        client.execute(new HttpGet("http://www.first.org"));
293        client.execute(new HttpGet("http://www.second.org"));
294        client.execute(new HttpGet("http://www.third.org"));
295
296        assertThat(((HttpUriRequest) Robolectric.getLatestSentHttpRequest()).getURI(),
297                equalTo(URI.create("http://www.third.org")));
298    }
299
300
301    @Test
302    public void shouldSupportConnectionTimeoutWithExceptions() throws Exception {
303        Robolectric.setDefaultHttpResponse(new TestHttpResponse() {
304            @Override
305            public HttpParams getParams() {
306                HttpParams httpParams = super.getParams();
307                HttpConnectionParams.setConnectionTimeout(httpParams, -1);
308                return httpParams;
309            }
310        });
311
312        DefaultHttpClient client = new DefaultHttpClient();
313        try {
314            client.execute(new HttpGet("http://www.nowhere.org"));
315        } catch (ConnectTimeoutException x) {
316            return;
317        }
318
319        fail("Exception should have been thrown");
320    }
321
322    @Test
323    public void shouldSupportSocketTimeoutWithExceptions() throws Exception {
324        Robolectric.setDefaultHttpResponse(new TestHttpResponse() {
325            @Override
326            public HttpParams getParams() {
327                HttpParams httpParams = super.getParams();
328                HttpConnectionParams.setSoTimeout(httpParams, -1);
329                return httpParams;
330            }
331        });
332
333        DefaultHttpClient client = new DefaultHttpClient();
334        try {
335            client.execute(new HttpGet("http://www.nowhere.org"));
336        } catch (ConnectTimeoutException x) {
337            return;
338        }
339
340        fail("Exception should have been thrown");
341    }
342
343    @Test(expected = IOException.class)
344    public void shouldSupportRealHttpRequests() throws Exception {
345        Robolectric.getFakeHttpLayer().interceptHttpRequests(false);
346        DefaultHttpClient client = new DefaultHttpClient();
347        client.execute(new HttpGet("http://www.this-host-should-not-exist-123456790.org:999"));
348    }
349}
350