scratch – Blame information for rev 87

Subversion Repositories:
Rev:
Rev Author Line No. Line
87 office 1 ======================
2 Testing Guzzle Clients
3 ======================
4  
5 Guzzle provides several tools that will enable you to easily mock the HTTP
6 layer without needing to send requests over the internet.
7  
8 * Mock subscriber
9 * Mock adapter
10 * Node.js web server for integration testing
11  
12 Mock Subscriber
13 ===============
14  
15 When testing HTTP clients, you often need to simulate specific scenarios like
16 returning a successful response, returning an error, or returning specific
17 responses in a certain order. Because unit tests need to be predictable, easy
18 to bootstrap, and fast, hitting an actual remote API is a test smell.
19  
20 Guzzle provides a mock subscriber that can be attached to clients or requests
21 that allows you to queue up a list of responses to use rather than hitting a
22 remote API.
23  
24 .. code-block:: php
25  
26 use GuzzleHttp\Client;
27 use GuzzleHttp\Subscriber\Mock;
28 use GuzzleHttp\Message\Response;
29  
30 $client = new Client();
31  
32 // Create a mock subscriber and queue two responses.
33 $mock = new Mock([
34 new Response(200, ['X-Foo' => 'Bar']), // Use response object
35 "HTTP/1.1 202 OK\r\nContent-Length: 0\r\n\r\n" // Use a response string
36 ]);
37  
38 // Add the mock subscriber to the client.
39 $client->getEmitter()->attach($mock);
40 // The first request is intercepted with the first response.
41 echo $client->get('/')->getStatusCode();
42 //> 200
43 // The second request is intercepted with the second response.
44 echo $client->get('/')->getStatusCode();
45 //> 202
46  
47 When no more responses are in the queue and a request is sent, an
48 ``OutOfBoundsException`` is thrown.
49  
50 History Subscriber
51 ==================
52  
53 When using things like the ``Mock`` subscriber, you often need to know if the
54 requests you expected to send were sent exactly as you intended. While the mock
55 subscriber responds with mocked responses, the ``GuzzleHttp\Subscriber\History``
56 subscriber maintains a history of the requests that were sent by a client.
57  
58 .. code-block:: php
59  
60 use GuzzleHttp\Client;
61 use GuzzleHttp\Subscriber\History;
62  
63 $client = new Client();
64 $history = new History();
65  
66 // Add the history subscriber to the client.
67 $client->getEmitter()->attach($history);
68  
69 $client->get('http://httpbin.org/get');
70 $client->head('http://httpbin.org/get');
71  
72 // Count the number of transactions
73 echo count($history);
74 //> 2
75 // Get the last request
76 $lastRequest = $history->getLastRequest();
77 // Get the last response
78 $lastRequest = $history->getLastResponse();
79  
80 // Iterate over the transactions that were sent
81 foreach ($history as $transaction) {
82 echo $transaction['request']->getMethod();
83 //> GET, HEAD
84 echo $transaction['response']->getStatusCode();
85 //> 200, 200
86 }
87  
88 The history subscriber can also be printed, revealing the requests and
89 responses that were sent as a string, in order.
90  
91 .. code-block:: php
92  
93 echo $history;
94  
95 ::
96  
97 > GET /get HTTP/1.1
98 Host: httpbin.org
99 User-Agent: Guzzle/4.0-dev curl/7.21.4 PHP/5.5.8
100  
101 < HTTP/1.1 200 OK
102 Access-Control-Allow-Origin: *
103 Content-Type: application/json
104 Date: Tue, 25 Mar 2014 03:53:27 GMT
105 Server: gunicorn/0.17.4
106 Content-Length: 270
107 Connection: keep-alive
108  
109 {
110 "headers": {
111 "Connection": "close",
112 "X-Request-Id": "3d0f7d5c-c937-4394-8248-2b8e03fcccdb",
113 "User-Agent": "Guzzle/4.0-dev curl/7.21.4 PHP/5.5.8",
114 "Host": "httpbin.org"
115 },
116 "origin": "76.104.247.1",
117 "args": {},
118 "url": "http://httpbin.org/get"
119 }
120  
121 > HEAD /get HTTP/1.1
122 Host: httpbin.org
123 User-Agent: Guzzle/4.0-dev curl/7.21.4 PHP/5.5.8
124  
125 < HTTP/1.1 200 OK
126 Access-Control-Allow-Origin: *
127 Content-length: 270
128 Content-Type: application/json
129 Date: Tue, 25 Mar 2014 03:53:27 GMT
130 Server: gunicorn/0.17.4
131 Connection: keep-alive
132  
133 Mock Adapter
134 ============
135  
136 In addition to using the Mock subscriber, you can use the
137 ``GuzzleHttp\Adapter\MockAdapter`` as the adapter of a client to return the
138 same response over and over or return the result of a callable function.
139  
140 .. code-block:: php
141  
142 use GuzzleHttp\Client;
143 use GuzzleHttp\Adapter\MockAdapter;
144 use GuzzleHttp\Adapter\TransactionInterface;
145 use GuzzleHttp\Message\Response;
146  
147 $mockAdapter = new MockAdapter(function (TransactionInterface $trans) {
148 // You have access to the request
149 $request = $trans->getRequest();
150 // Return a response
151 return new Response(200);
152 });
153  
154 $client = new Client(['adapter' => $mockAdapter]);
155  
156 Test Web Server
157 ===============
158  
159 Using mock responses is almost always enough when testing a web service client.
160 When implementing custom :doc:`HTTP adapters <adapters>`, you'll need to send
161 actual HTTP requests in order to sufficiently test the adapter. However, a
162 best practice is to contact a local web server rather than a server over the
163 internet.
164  
165 - Tests are more reliable
166 - Tests do not require a network connection
167 - Tests have no external dependencies
168  
169 Using the test server
170 ---------------------
171  
172 .. warning::
173  
174 The following functionality is provided to help developers of Guzzle
175 develop HTTP adapters. There is no promise of backwards compatibility
176 when it comes to the node.js test server or the ``GuzzleHttp\Tests\Server``
177 class. If you are using the test server or ``Server`` class outside of
178 guzzlehttp/guzzle, then you will need to configure autoloading and
179 ensure the web server is started manually.
180  
181 .. hint::
182  
183 You almost never need to use this test web server. You should only ever
184 consider using it when developing HTTP adapters. The test web server
185 is not necessary for mocking requests. For that, please use the
186 Mock subcribers and History subscriber.
187  
188 Guzzle ships with a node.js test server that receives requests and returns
189 responses from a queue. The test server exposes a simple API that is used to
190 enqueue responses and inspect the requests that it has received.
191  
192 Any operation on the ``Server`` object will ensure that
193 the server is running and wait until it is able to receive requests before
194 returning.
195  
196 .. code-block:: php
197  
198 use GuzzleHttp\Client;
199 use GuzzleHttp\Tests\Server;
200  
201 // Start the server and queue a response
202 Server::enqueue("HTTP/1.1 200 OK\r\n\Content-Length: 0r\n\r\n");
203  
204 $client = new Client(['base_url' => Server::$url]);
205 echo $client->get('/foo')->getStatusCode();
206 // 200
207  
208 ``GuzzleHttp\Tests\Server`` provides a static interface to the test server. You
209 can queue an HTTP response or an array of responses by calling
210 ``Server::enqueue()``. This method accepts a string representing an HTTP
211 response message, a ``GuzzleHttp\Message\ResponseInterface``, or an array of
212 HTTP message strings / ``GuzzleHttp\Message\ResponseInterface`` objects.
213  
214 .. code-block:: php
215  
216 // Queue single response
217 Server::enqueue("HTTP/1.1 200 OK\r\n\Content-Length: 0r\n\r\n");
218  
219 // Clear the queue and queue an array of responses
220 Server::enqueue([
221 "HTTP/1.1 200 OK\r\n\Content-Length: 0r\n\r\n",
222 "HTTP/1.1 404 Not Found\r\n\Content-Length: 0r\n\r\n"
223 ]);
224  
225 When a response is queued on the test server, the test server will remove any
226 previously queued responses. As the server receives requests, queued responses
227 are dequeued and returned to the request. When the queue is empty, the server
228 will return a 500 response.
229  
230 You can inspect the requests that the server has retrieved by calling
231 ``Server::received()``. This method accepts an optional ``$hydrate`` parameter
232 that specifies if you are retrieving an array of HTTP requests as strings or an
233 array of ``GuzzleHttp\Message\RequestInterface`` objects.
234  
235 .. code-block:: php
236  
237 foreach (Server::received() as $response) {
238 echo $response;
239 }
240  
241 You can clear the list of received requests from the web server using the
242 ``Server::flush()`` method.
243  
244 .. code-block:: php
245  
246 Server::flush();
247 echo count(Server::received());
248 // 0