gpt4 book ai didi

phpspec 单元测试 - 使用 ioc/service registry 来交付要测试的具体类

转载 作者:搜寻专家 更新时间:2023-10-31 21:08:18 26 4
gpt4 key购买 nike

我是测试新手,我不确定我的做法是否正确:

我不想对特定类进行单元测试,而是对从我的 ioc 容器中解析出来的任何类进行单元测试。在 ioc 容器中,我将接口(interface)绑定(bind)到具体类,如下所示:

示例(我使用的是 Laravel 5):

// in a service provider
public function register(){

$this->app->bind('FooInterface', function() {
return new SomeConcreteFoo;
});
}

然后我想针对 FooInterface 而不是 SomeConcreteFoo 编写单元测试,后者稍后可以与其他类交换。

我想这样做的原因是,在我看来,相关测试应该针对我的 ioc 容器返回的任何内容,因为这就是我将在应用程序中使用的内容。在我看来,测试应该在接口(interface)级别完成,因为这是我定义应用程序其余部分对我的类的期望的地方。

我很难找到有关如何执行此操作的任何信息,这表明我可能以错误的方式思考这个问题。例如,也许我想要完成的更像是集成测试而不是单元测试。

所以第一个问题是:我是否正在考虑以正确的方式进行测试?如果我不是 - 您对替代测试路径的最佳实践有什么建议吗?

第二个问题:如果我的想法是正确的——我该如何设置 phpspec 来使用 Laravel IOC 容器,这样我就可以针对 IOC 返回的任何内容进行测试。

最佳答案

I want to not to do a unit test on a specific class but on whatever class get resolved out of my ioc container. In the ioc container I bind my interfaces to concrete classes, like so [...]

这不是编写单元测试的方式。单元测试是关于孤立地描述一个类的行为,因此实际创建的唯一真实对象是被测类(有时是简单的值对象)。

Then I want to write unit test against FooInterface and not SomeConcreteFoo which could be swapped out with some other class at a later point.

这确实是您应该编写单元测试的方式。更喜欢协作者的界面。

每个模拟框架都支持此功能,并且会为您创建测试替身,而不会强制您提供特定的实现。

class BarSpec extends ObjectBehavior
{
function it_does_amazing_things(FooInterface $foo)
{
$results = ['a', 'b', 'c'];

$foo->find('something')->willReturn($results);

$this->findMeSometing()->shouldReturn($results);
}
}

在此特定示例中,PhpSpec 将使用 Prophecy(其模拟框架)创建 FooInterface 的测试替身并将其注入(inject)示例方法。您对该对象的处理决定了它是伪造的、 stub 的还是模拟的。

The reason I want to do this is that it seems to me that the relevant testing should target whatever my ioc container returns, since that is what I'll be using in the application.

如上所述,单元测试侧重于单个类的行为。它的合作者通常是伪造的。这是出于几个原因。其中之一是速度。另一个是反馈。如果测试失败,我们将得到关于哪个类被破坏的明确反馈。如果您正在创建所有协作者,而不是使用测试替身,那么一个错误可能会使您的整个测试套件变红。我什至不会提到维护和创建所有需要的对象会有多困难(尽管容器在这里可以提供帮助)。

请记住,编写单元测试更像是一种设计事件,而不是测试事件。

For instance maybe what I'm trying to accomplish is more like an integration test rather than a unit test.

的确如此。阅读有关测试金字塔的更多信息。大多数测试应该是单元测试。然后,您应该进行一定数量的集成和验收测试,这些测试将同时执行多个类(class)。您需要比集成测试更多的单元测试的原因是后者更脆弱并且更难维护/更改它们。

使用 PHPUnit 进行集成测试。 PhpSpec 不是这项工作的正确工具。 PhpSpec 非常适合设计您的类(编写单元测试),尤其是当您先进行测试时。

The second question: In case my thinking is sound - how do I setup phpspec to make use of the Laravel IOC container, so that I can test against whatever the IOC returns..

你不知道。不过,您可以考虑在集成测试中使用容器。

一些阅读:

关于phpspec 单元测试 - 使用 ioc/service registry 来交付要测试的具体类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28266118/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com