1Test::LWP::UserAgent(3)User Contributed Perl DocumentatioTnest::LWP::UserAgent(3)
2
3
4

NAME

6       Test::LWP::UserAgent - A LWP::UserAgent suitable for simulating and
7       testing network calls
8

VERSION

10       version 0.036
11

SYNOPSIS

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

DESCRIPTION

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

METHODS

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

Usage with SOAP requests

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

MOTIVATION

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

ACKNOWLEDGEMENTS

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

SEE ALSO

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

SUPPORT

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

AUTHOR

406       Karen Etheridge <ether@cpan.org>
407

CONTRIBUTOR

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)
Impressum