Moose 类的依赖注入
我有一个 Moose 类,需要发送 Foo::Request
类型的请求。我需要从外部访问此依赖项,以便我可以在测试中轻松交换请求实现。我想出了以下属性:
has request_builder => (
is => 'rw',
isa => 'CodeRef',
default => sub {
sub { Foo::Request->new(@_) }
}
);
然后在代码中:
my $self = shift;
my $request = $self->request_builder->(path => …);
在测试中:
my $tested_class = …;
my $request = Test::MockObject->new;
$request->mock(…);
$tested_class->request_builder(sub { $request });
是否有更简单/更惯用的解决方案?
I have a Moose class that needs to send requests of type Foo::Request
. I need to make this dependency accessible from the outside, so that I can easily exchange the request implementation in tests. I came up with the following attribute:
has request_builder => (
is => 'rw',
isa => 'CodeRef',
default => sub {
sub { Foo::Request->new(@_) }
}
);
And then in code:
my $self = shift;
my $request = $self->request_builder->(path => …);
And in tests:
my $tested_class = …;
my $request = Test::MockObject->new;
$request->mock(…);
$tested_class->request_builder(sub { $request });
Is there a more simple / more idiomatic solution?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
如何使用 Moose::Util::apply_all_roles 在测试中动态应用角色?我想用这个已经有一段时间了,但还没有借口。我认为它是这样运作的。
首先,稍微修改您的原始属性:
然后创建一个 Test::RequestBuilder 角色:
同时在 't/my_client_thing.t' 中您将编写如下内容:
请参阅 Moose::Manual::Roles 了解更多信息。
How about applying a role dynamically in your tests with Moose::Util::apply_all_roles? I have been wanting to use this for a while, but haven't had an excuse yet. Here is how I think it would work.
First, modify your original attribute slightly:
Then create a Test::RequestBuilder role:
Meanwhile in 't/my_client_thing.t' you would write something like this:
See Moose::Manual::Roles for more info.
我的建议是,按照 chromatic 文章中的模型(Mike 上面的评论),是这样的:
在你的类中:
在你的测试中:
完全按照你的代码所做的操作,并进行以下改进:
request
属性是一个随时可用的对象;无需取消引用子引用My suggestion, following the model in chromatic's article (comment above by Mike), is this:
In your class:
In your test:
Does exactly what your code does, with the following refinements:
request
attribute is a ready-to-use object; no need to dereference the sub ref考虑这种方法:
在您的 Moose 类中定义一个名为
make_request
的“抽象”方法。然后定义两个实现make_request
的角色 - 一个调用Foo::Request->new
,另一个调用Test::MockObject->new< /代码>。
示例:
您的主类和两个角色:
如果您想测试您的主类,请将其与“MakeRequestWithMock”角色混合:
如果您想将其与“make_request”的 Foo 实现一起使用,请将其与“MakeRequestWithFoo”混合' 角色。
一些优点:
您将只加载您需要的模块。例如,
TestVersionOfMainMooseClass
类将不会加载模块Foo::Request
。您可以将
make_request
实现相关/所需的数据添加为新类的实例成员。例如,您使用 CODEREF 的原始方法可以通过以下角色实现:要使用此类,您需要为
request_builder
提供初始值设定项,例如:作为最终考虑,您编写的角色可能是可与其他类一起使用。
Consider this approach:
In your Moose class define an 'abstract' method called
make_request
. Then define two roles which implementmake_request
- one which callsFoo::Request->new
and another one which callsTest::MockObject->new
.Example:
Your main class and the two roles:
If you want to test your main class, mix it with the 'MakeRequestWithMock' role:
If you want to use it with the Foo implementation of 'make_request', mix it in with the 'MakeRequestWithFoo' role.
Some advantages:
You will only load in modules that you need. For instance, the class
TestVersionOfMainMooseClass
will not load the moduleFoo::Request
.You can add data that is relevant/required by your implementation of
make_request
as instance members of your new class. For example, your original approach of using a CODEREF can be implemented with this role:To use this class you need to supply an initializer for
request_builder
, e.g.:As a final consideration, the roles you write might be usable with other classes.
我知道这篇文章有点旧,但对于任何提到这个问题的人来说,现在请求者可以使用像 这样的框架面包::板。
I know this post is a little old, but for anyone referring to this question now the requester could use a framework like Bread::Board.