This article was originally published on the Perl Advent Calendar 2012.
Test::LWP::UserAgent is a module I wrote after writing several networking client libraries for $work with inconsistent and spotty test coverage -- what I most wanted to do was fully simulate the server end of a network connection, without having to delve deeply into LWP's internal implementation, nor mock a lot of methods, which the traditional mock object approach would require.
Exploring the options available led me to Yury Zavarin's Test::Mock::LWP::Dispatch, whose API I adapted into the initial version of Test::LWP::UserAgent. It behaves exactly like LWP::UserAgent, one of the main networking client libraries in perl, in all respects except for the portion that actually sends the request out to the network - at that point it returns the first response that you have preconfigured that matches the outbound request.
my $useragent = Test::LWP::UserAgent->new; $useragent->map_response(qr/example.com/, HTTP::Response->new(200)); my $response = $useragent->get('http://example.com'); # prints 200 say $response->code; $response = $useragent->get('http://google.com'); # prints 404 say $response->code;
In the above example, no outbound request passing through this useragent will use the live network (this is the default behaviour). Any request whose URI matches /example.com/ will receive an HTTP 200 response, and the remaining requests will return a 404.
/example.com/
If, however, you wish to only capture some requests, while letting the remainder use the network normally, you can enable the network_fallback feature:
network_fallback
my $useragent = Test::LWP::UserAgent->new; $useragent->network_fallback(1); $useragent->map_response(qr/example.com/, HTTP::Response->new(200)); my $response = $useragent->get('http://example.com'); # prints 200 say $response->code; $response = $useragent->get('http://google.com'); # prints 200 say $response->code;
And indeed if you inspect the $response object returned, you will see that it contains the actual network response from contacting http://google.com.
$response
Configuration can also be done globally, if you want all useragents in your program to use the same settings (or if you do not have direct control over the actual useragent object being used, but just its class):
Test::LWP::UserAgent->map_response(...); my $response = Test::LWP::UserAgent->new->request(...);
Test::LWP::UserAgent inherits from LWP::UserAgent, so it satisfies isa()/@ISA requirements that you may have via Moose or another system that uses type checking. This means that all the normal options available in LWP::UserAgent are still available to you, and work identically, for example:
isa()
@ISA
my $useragent = Test::LWP::UserAgent->new( timeout => 10, cookie_jar => { file => "$ENV{HOME}/.cookies.txt" }, );
You can also use Test::LWP::UserAgent to connect to a local PSGI application seamlessly, which can be very useful when you have a client and server installed on the same box but do not want to fuss with separate code for handling this case, or if you want more fine-grained control over what responses to send:
my $app = Plack::Util::load_psgi('./myapp.psgi'); $useragent->register_psgi('mytestdomain.com', $app); my $response = $useragent->request(...);
Use Test::LWP::UserAgent to control data flow that you would otherwise receive over the network, to test your application's handling of that data.
The code examples above are fleshed out as fully-working code in the examples/ directory under http://metacpan.org/release/Test-LWP-UserAgent, along with a detailed example of some unit tests for a hypothetical networking client library.
Karen Etheridge (ether) http://metacpan.org/author/ETHER http://github.com/karenetheridge
To install Test::LWP::UserAgent, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Test::LWP::UserAgent
CPAN shell
perl -MCPAN -e shell install Test::LWP::UserAgent
For more information on module installation, please visit the detailed CPAN module installation guide.