/ / Test :: MockModule твърди, че “методът не съществува” - perl, mocking

Тест :: MockModule твърди, че "методът не съществува" - perl, подигравка

Опитвам се да се подигравам с функция в Net :: Twitter:

use strict;
use warnings;
use Test::MockModule;

my $mock = Test::MockModule->new("Net::Twitter");
$mock->redefine("update", sub {
# ...
});

но когато стартирам това, получавам:

Net :: Twitter :: update не съществува! на wtf.pl ред 8.

Защо е така и как всъщност мога да се подигравам Net::Twitter::update функционира?

Отговори:

5 за отговор № 1

Съобщението за грешка означава, че не може да бъде намерено Net::Twitter::update за презаписване. Това е доста ясно. Въпросът е, защо?.

Ако погледнете a Net :: Twitter обект с Данни :: Printerще видите, че наистина няма update метод. Всъщност това дори не е обект от типа Net::Twitter.

use Net::Twitter;
use Data::Printer;

my $t = Net::Twitter->new;
p $t;

На моята машина с най-новата инсталирана Net :: Twitter, тя е Net::Twitter_v4_01042_with__Legacy, което вероятно е динамично създаден пакет.

Net::Twitter_v4_01042_with__Legacy  {
Parents       Net::Twitter::Core
public methods (22) : apihost, apirealm, apiurl, arrayref_on_error, BUILD, DESTROY, has_error, http_code, http_message, is_list_member, is_list_subscriber, is_subscribed_list, meta, new, searchapiurl, trends, tvhost, tvrealm, tvurl, twittervision, update_twittervision, upload_url
private methods (5) : _clear_error, _error_return_val, _http_response, _parse_result, _twitter_error
internals: {
apirealm               "Twitter API",
apiurl                 "https://api.twitter.com/1",
arrayref_on_error      0,
clientname             "Perl Net::Twitter",
clienturl              "http://search.cpan.org/dist/Net-Twitter/",
clientver              4.01042,
decode_html_entities   0,
_error_return_val      undef,
_json_handler          Cpanel::JSON::XS,
<<MOP>>                Class::MOP::Class::Immutable::Moose::Meta::Class,
netrc_machine          "api.twitter.com",
searchapiurl           "https://search.twitter.com",
source                 "twitterpm",
ssl                    1,
tvhost                 "twittervision.com:80",
tvrealm                "Web Password",
tvurl                  "http://twittervision.com",
twittervision          0,
upload_url             "https://upload.twitter.com/1",
useragent              "Net::Twitter/4.01042 (Perl)",
useragent_args         {},
useragent_class        "LWP::UserAgent"
}
}

Ако опитате търся си sub update в цялата дистрибуция на Net :: Twitter, Вие няма да намерите нищо. Не е част от роля, просто не съществува.

Но това не означава, че не е там. Изкопах малко по-дълбоко и намерих един update в мрежата :: Twitter :: Role :: API :: REST, Определя се с помощта на twitter_api_method функция от Net :: Twitter :: API, Той прави куп неща и след това използва мета слоя на Moose, за да инсталира метода в някой клас - вероятно Net::Twitter_v4_01042_with__Legacy на моята машина '- и дори носи свой собствен клас мета метод Net :: Twitter :: :: Мета Метод.

Така че е доста очевидно защо Тест :: MockModule нямаше да намери Net::Twitter::update, Просто никога

Но как да се подиграваме за тестване?

Вярвам, че най-простият подход, макар със сигурност не е много хубав, е да се презапише update в пакета, в който съществува. За това трябва да създадете обект и да проверите.

use strict;
use warnings;
use Test::MockModule;
use Net::Twitter;

my $mock = Test::MockModule->new( ref( Net::Twitter->new ) );
$mock->redefine(
"update",
sub {
... # will die with "unimplemented"
}
);

my $nt = Net::Twitter->new->update;

Този код е малко разточителен, защото трябва да създаде обект само за да провери в кой пакет е стигнал, но работи.

Не се изпълнява в /home/simbabque/code/scratch/scratch.pl ред 236.