To test the ubiquitous (and awesome) LWP::UserAgent module, I use Test::Mock::LWP. It works as advertised, with minimal code. However, I still found myself writing a little plumbing. Here are two code snippets that I use when using Test::Mock::LWP.
First, a way of mocking code using LWP::UserAgent’s requests_redirectable
array, as in
sub _new_agent {
my $agent = LWP::UserAgent->new;
push @{$agent->requests_redirectable}, 'POST';
return $agent;
}
This won’t work with vanilla Test::Mock::LWP, as requests_redirectable is not a method and therefore cannot be mocked – a small flaw in UserAgent’s API. To circumvent the problem, mock your own UserAgent creation sub (you did encapsulate that, didn’t you):
use Test::MockObject;
# In addition to Test::Mock::LWP, we also need to mock our own
# wrapper for LWP::UserAgent->new, as it needs UserAgent's
# requests_redirectable array and the mock doesn't have that.
Test::MockObject->new()
->fake_module('My::Foo',
'_new_agent' => sub { return LWP::UserAgent->new; }
);
Second, just a tiny sub to make things nicer, IMHO: it provides a clean abstraction to get the latest requested URL. It’s useful if that’s all you want to test. This makes tests nicer to read and isolates them from the mocking module. It also encapsulates the magic index we need to get the requested URL from the request header array. The index is 2 here, this works for code making requests using HTTP::Request::Common. It’s probably different if you use HTTP::Request directly, but the test runner’s expected/actual output will quickly show you where the URL hides.
sub latest_requested_url {
return scalar $Mock_request->new_args()->[2];
}