Рассмотрим этот подход:
В вашем классе Moose определите «абстрактный» метод с именем make_request
. Затем определите две роли, которые реализуют make_request
- одну, которая вызывает Foo::Request->new
, а другую - Test::MockObject->new
.
.
Пример:
Ваш основной класс и две роли:
package MainMooseClass;
use Moose;
...
# Note: this class requires a role that
# provides an implementation of 'make_request'
package MakeRequestWithFoo;
use Moose::Role;
use Foo::Request; # or require it
sub make_request { Foo::Request->new(...) }
package MakeRequestWithMock;
use Moose::Role;
use Test::MockRequest; # or require it
sub make_request { Test::MockRequest->new(...) }
Если вы хотите проверить свой основной класс, смешайте его с ролью «MakeRequestWithMock»:
package TestVersionOfMainMooseClass;
use Moose;
extends 'MainMooseClass';
with 'MakeRequestWithMock';
package main;
my $test_object = TestVersionOfMainMooseClass->new(...);
Если вы хотите использовать его с реализацией Foo make_request, смешайте его с ролью MakeRequestWithFoo.
Некоторые преимущества:
Вы будете загружать только те модули, которые вам нужны. Например, класс TestVersionOfMainMooseClass
будет не загружать модуль Foo::Request
.
Вы можете добавить данные, которые являются релевантными / требующимися вашей реализацией make_request
, в качестве членов экземпляра вашего нового класса. Например, ваш оригинальный подход с использованием CODEREF может быть реализован с помощью этой роли:
package MakeRequestWithCodeRef;
use Moose::Role;
has request_builder => (
is => 'rw',
isa => 'CodeRef',
required => 1,
);
sub make_request { my $self = shift; $self->request_builder->(@_) };
Для использования этого класса вам необходимо предоставить инициализатор для request_builder
, например ::
package Example;
use Moose;
extends 'MainMooseClass';
with 'MakeRequestWithCodeRef';
package main;
my $object = Example->new(request_builder => sub { ... });
В качестве заключительного замечания, роли, которые вы пишете, могут быть использованы с другими классами.