1Test::LWP::UserAgent(3)User Contributed Perl DocumentatioTnest::LWP::UserAgent(3)
2
3
4
6 Test::LWP::UserAgent - A LWP::UserAgent suitable for simulating and
7 testing network calls
8
10 version 0.036
11
13 In your application code:
14
15 use URI;
16 use HTTP::Request::Common;
17 use LWP::UserAgent;
18
19 my $useragent = $self->useragent || LWP::UserAgent->new;
20
21 my $uri = URI->new('http://example.com');
22 $uri->port('3000');
23 $uri->path('success');
24 my $request = POST($uri, a => 1);
25 my $response = $useragent->request($request);
26
27 Then, in your tests:
28
29 use Test::LWP::UserAgent;
30 use Test::More;
31
32 my $useragent = Test::LWP::UserAgent->new;
33 $useragent->map_response(
34 qr{example.com/success}, HTTP::Response->new('200', 'OK', ['Content-Type' => 'text/plain'], ''));
35 $useragent->map_response(
36 qr{example.com/fail}, HTTP::Response->new('500', 'ERROR', ['Content-Type' => 'text/plain'], ''));
37
38 # now, do something that sends a request, and test how your application
39 # responds to that response
40
42 This module is a subclass of LWP::UserAgent which overrides a few key
43 low-level methods that are concerned with actually sending your request
44 over the network, allowing an interception of that request and
45 simulating a particular response. This greatly facilitates testing of
46 networking client code where the server follows a known protocol.
47
48 The synopsis describes a typical case where you want to test how your
49 application reacts to various responses from the server. This module
50 will let you send back various responses depending on the request,
51 without having to set up a real server to test against. This can be
52 invaluable when you need to test edge cases or error conditions that
53 are not normally returned from the server.
54
55 There are a lot of different ways you can set up the response mappings,
56 and hook into this module; see the documentation for the individual
57 interface methods.
58
59 You can use a PSGI app to handle the requests - see
60 examples/call_psgi.t in this distribution, and also "register_psgi"
61 below.
62
63 OR, you can route some or all requests through the network as normal,
64 but still gain the hooks provided by this class to test what was sent
65 and received:
66
67 my $useragent = Test::LWP::UserAgent->new(network_fallback => 1);
68
69 or:
70
71 $useragent->map_network_response(qr/real.network.host/);
72
73 # ... generate a request...
74
75 # and then in your tests:
76 is(
77 $useragent->last_useragent->timeout,
78 180,
79 'timeout was overridden properly',
80 );
81 is(
82 $useragent->last_http_request_sent->uri,
83 'uri my code should have constructed',
84 );
85 is(
86 $useragent->last_http_response_received->code,
87 '200',
88 'I should have gotten an OK response',
89 );
90
91 Ensuring the right useragent is used
92 Note that LWP::UserAgent itself is not monkey-patched - you must use
93 this module (or a subclass) to send your request, or it cannot be
94 caught and processed.
95
96 One common mechanism to swap out the useragent implementation is via a
97 lazily-built Moose(-like) attribute; if no override is provided at
98 construction time, default to "LWP::UserAgent->new(%options)".
99
100 Additionally, most methods can be called as class methods, which will
101 store the settings globally, so that any instance of
102 Test::LWP::UserAgent can use them, which can simplify some of your
103 application code.
104
106 "new"
107 Accepts all options as in LWP::UserAgent, including "use_eval", an
108 undocumented boolean which is enabled by default. When set, sending the
109 HTTP request is wrapped in an "eval {}", allowing all exceptions to be
110 caught and an appropriate error response (usually HTTP 500) to be
111 returned. You may want to unset this if you really want to test
112 extraordinary errors within your networking code. Normally, you should
113 leave it alone, as LWP::UserAgent and this module are capable of
114 handling normal errors.
115
116 Plus, this option is added:
117
118 • "network_fallback => <boolean>"
119
120 If true, requests passing through this object that do not match a
121 previously-configured mapping or registration will be directed to
122 the network. (To only divert matched requests rather than
123 unmatched requests, use "map_network_response", see below.)
124
125 This option is also available as a read/write accessor via
126 "$useragent->network_fallback(<value?>)".
127
128 All other methods below may be called on a specific object instance, or
129 as a class method. If the method invoked on a blessed object, the
130 action performed or data returned is limited to just that object; if it
131 is called as a class method, the action or data is global and affects
132 all instances (although specific instances may have overrides; see
133 below).
134
135 "map_response($request_specification, $http_response)"
136 With this method, you set up what HTTP::Response should be returned for
137 each request received.
138
139 The request match specification can be described in multiple ways:
140
141 • string
142
143 The string is matched identically against the "host" field of the
144 URI in the request.
145
146 $test_ua->map_response('example.com', HTTP::Response->new('500'));
147
148 • regexp
149
150 The regexp is matched against the URI in the request.
151
152 $test_ua->map_response(qr{foo/bar}, HTTP::Response->new('200'));
153 $test_ua->map_response(qr{baz/quux}, HTTP::Response->new('500'));
154
155 • code
156
157 The provided coderef is passed a single argument, the
158 HTTP::Request, and returns a boolean indicating if there is a
159 match.
160
161 # matches all GET and POST requests
162 $test_ua->map_response(sub {
163 my $request = shift;
164 return 1 if $request->method eq 'GET' || $request->method eq 'POST';
165 },
166 HTTP::Response->new('200'),
167 );
168
169 • HTTP::Request object
170
171 The HTTP::Request object is matched identically (including all
172 query parameters, headers etc) against the provided object.
173
174 The response can be represented in multiple ways:
175
176 • a literal HTTP::Response object:
177
178 HTTP::Response->new(...);
179
180 • as a coderef that is run at the time of matching, with the request
181 passed as the single argument:
182
183 sub {
184 my $request = shift;
185 return HTTP::Response->new(...);
186 }
187
188 •
189
190
191 a blessed object that implements the "request" method, which will
192 be saved as a coderef thusly (this allows you to use your own
193 dispatcher implementation):
194
195 sub {
196 my $request = shift;
197 return $response->request($request);
198 }
199
200 Instance mappings take priority over global (class method) mappings -
201 if no matches are found from mappings added to the instance, the global
202 mappings are then examined. When no matches have been found, a 404
203 response is returned.
204
205 This method returns the "Test::LWP::UserAgent" object or class.
206
207 map_network_response($request_specification)
208 Same as "map_response" above, only requests that match this
209 specification will not use a response that you specify, but instead
210 uses a real LWP::UserAgent to dispatch your request to the network.
211
212 If called on an instance, all options passed to the constructor (e.g.
213 timeout) are used for making the real network call. If called as a
214 class method, a pristine LWP::UserAgent object with no customized
215 options will be used instead.
216
217 This method returns the "Test::LWP::UserAgent" object or class.
218
219 unmap_all(instance_only?)
220 When called as a class method, removes all mappings set up globally
221 (across all objects). Mappings set up on an individual object will
222 still remain.
223
224 When called as an object method, removes all mappings both globally and
225 on this instance, unless a true value is passed as an argument, in
226 which only mappings local to the object will be removed. (Any true
227 value will do, so you can pass a meaningful string.)
228
229 This method returns the "Test::LWP::UserAgent" object or class.
230
231 "register_psgi($domain, $app)"
232 Register a particular PSGI app (code reference) to be used when
233 requests for a domain are received (matches are made exactly against
234 "$request->uri->host"). The request is passed to the $app for
235 processing, and the PSGI response is converted back to an
236 HTTP::Response (you must already have loaded HTTP::Message::PSGI or
237 equivalent, as this is not done for you).
238
239 You can also use "register_psgi" with a regular expression as the first
240 argument, or any of the other forms used by "map_response", if you
241 wish, as calling "$test_ua->register_psgi($domain, $app)" is equivalent
242 to:
243
244 $test_ua->map_response(
245 $domain,
246 sub { HTTP::Response->from_psgi($app->($_[0]->to_psgi)) },
247 );
248
249 This feature is useful for testing your PSGI applications, or for
250 simulating a server so as to test your client code.
251
252 You might find using Plack::Test or Plack::Test::ExternalServer easier
253 for your needs, so check those out as well.
254
255 This method returns the "Test::LWP::UserAgent" object or class.
256
257 "unregister_psgi($domain, instance_only?)"
258 When called as a class method, removes a domain->PSGI app entry that
259 had been registered globally. Some mappings set up on an individual
260 object may still remain.
261
262 When called as an object method, removes a domain registration that was
263 made both globally and locally, unless a true value was passed as the
264 second argument, in which case only the registration local to the
265 object will be removed. This allows a different mapping made globally
266 to take over.
267
268 If you want to mask a global registration on just one particular
269 instance, then add "undef" as a mapping on your instance:
270
271 $useragent->map_response($domain, undef);
272
273 This method returns the "Test::LWP::UserAgent" object or class.
274
275 "last_http_request_sent"
276 The last HTTP::Request object that this object (if called on an object)
277 or module (if called as a class method) processed, whether or not it
278 matched a mapping you set up earlier.
279
280 Note that this is also available via
281 "last_http_response_received->request".
282
283 "last_http_response_received"
284 The last HTTP::Response object that this module returned, as a result
285 of a mapping you set up earlier with "map_response". You shouldn't
286 normally need to use this, as you know what you responded with - you
287 should instead be testing how your code reacted to receiving this
288 response.
289
290 "last_useragent"
291 The last Test::LWP::UserAgent object that was used to send a request.
292 Obviously this only provides new information if called as a class
293 method; you can use this if you don't have direct control over the
294 useragent itself, to get the object that was used, to verify options
295 such as the network timeout.
296
297 "network_fallback"
298 Getter/setter method for the network_fallback preference that will be
299 used on this object (if called as an instance method), or globally, if
300 called as a class method. Note that the actual behaviour used on an
301 object is the ORed value of the instance setting and the global
302 setting.
303
304 send_request($request)
305 This is the only method from LWP::UserAgent that has been overridden,
306 which processes the HTTP::Request, sends to the network, then creates
307 the HTTP::Response object from the reply received. Here, we loop
308 through your local and global domain registrations, and local and
309 global mappings (in this order) and returns the first match found;
310 otherwise, a simple 404 response is returned (unless "network_fallback"
311 was specified as a constructor option, in which case unmatched requests
312 will be delivered to the network.)
313
314 All other methods from LWP::UserAgent are available unchanged.
315
317 SOAP::Lite
318 To use this module when communicating via SOAP::Lite with a SOAP server
319 (either a real one, with live network requests, see above or with one
320 simulated with mapped responses), simply do this:
321
322 use SOAP::Lite;
323 use SOAP::Transport::HTTP;
324 $SOAP::Transport::HTTP::Client::USERAGENT_CLASS = 'Test::LWP::UserAgent';
325
326 You must then make all your configuration changes and mappings
327 globally.
328
329 See also "CHANGING THE DEFAULT USERAGENT CLASS" in SOAP::Transport.
330
331 XML::Compile::SOAP
332 When using XML::Compile::SOAP with a compiled WSDL, you can change the
333 useragent object via XML::Compile::Transport::SOAPHTTP:
334
335 my $call = $wsdl->compileClient(
336 $interface_name,
337 transport => XML::Compile::Transport::SOAPHTTP->new(
338 user_agent => $useragent,
339 address => $wsdl->endPoint,
340 ),
341 );
342
343 See also "Adding HTTP headers" in XML::Compile::SOAP::FAQ.
344
346 Most mock libraries on the CPAN use Test::MockObject, which is widely
347 considered not good practice (among other things, @ISA is violated, it
348 requires knowing far too much about the module's internals, and is very
349 clumsy to work with). (This blog entry is one of many that chronicles
350 its issues.)
351
352 This module is a direct descendant of LWP::UserAgent, exports nothing
353 into your namespace, and all access is via method calls, so it is fully
354 inheritable should you desire to add more features or override some
355 bits of functionality.
356
357 (Aside from the constructor), it only overrides the one method in
358 LWP::UserAgent that issues calls to the network, so real HTTP::Request
359 and HTTP::Headers objects are used throughout. It provides a method
360 ("last_http_request_sent") to access the last HTTP::Request, for
361 testing things like the URI and headers that your code sent to
362 LWP::UserAgent.
363
365 AirG Inc. <http://corp.airg.com>, my former employer, and the first
366 user of this distribution.
367
368 mst - Matt S. Trout <mst@shadowcat.co.uk>, for the better name of this
369 distribution, and for the PSGI registration concept.
370
371 Also Yury Zavarin, whose Test::Mock::LWP::Dispatch inspired me to write
372 this module, and from where I borrowed some aspects of the API.
373
375 • Perl advent article, 2012
376 <http://www.perladvent.org/2012/2012-12-12.html>
377
378 • Test::Mock::LWP::Dispatch
379
380 • Test::Mock::LWP::UserAgent
381
382 • URI, HTTP::Request, HTTP::Response
383
384 • LWP::UserAgent
385
386 • PSGI, HTTP::Message::PSGI, LWP::Protocol::PSGI,
387
388 • Plack::Test, Plack::Test::ExternalServer
389
391 Bugs may be submitted through the RT bug tracker
392 <https://rt.cpan.org/Public/Dist/Display.html?Name=Test-LWP-UserAgent>
393 (or bug-Test-LWP-UserAgent@rt.cpan.org <mailto:bug-Test-LWP-
394 UserAgent@rt.cpan.org>).
395
396 There is also a mailing list available for users of this distribution,
397 at <http://lists.perl.org/list/perl-qa.html>.
398
399 There is also an irc channel available for users of this distribution,
400 at "#perl" on "irc.perl.org" <irc://irc.perl.org/#perl-qa>.
401
402 I am also usually active on irc, as 'ether' at "irc.perl.org" and
403 "irc.libera.chat".
404
406 Karen Etheridge <ether@cpan.org>
407
409 Tom Hukins <tom@eborcom.com>
410
412 This software is copyright (c) 2012 by Karen Etheridge.
413
414 This is free software; you can redistribute it and/or modify it under
415 the same terms as the Perl 5 programming language system itself.
416
417
418
419perl v5.38.0 2023-07-21 Test::LWP::UserAgent(3)