【问题标题】:Testing call of multiple methods in phpspec在phpspec中测试多个方法的调用
【发布时间】:2015-12-26 18:37:35
【问题描述】:

过去我总是偶然发现 phpspec 的某个问题:

假设我有一个方法可以调用另一个对象的多个方法

class Caller {
    public function call(){
       $this->receiver->method1();
       ...
       $this->receiver->method2();
    }
}

在 BDD 中,我首先会编写一个测试,以确保调用 method1

function it_calls_method1_of_receiver(Receiver $receiver){
    $receiver->method1()->shouldBeCalled();
    $this->call();
}

然后我会编写下一个测试以确保将调用 method2

function it_calls_method2_of_receiver(Receiver $receiver){
    $receiver->method2()->shouldBeCalled();
    $this->call();
}

但是这个测试在 phpspec 中失败了,因为 method1method2 之前被调用。 为了满足 phpspec,我必须检查两个方法调用。

 function it_calls_method2_of_receiver(Receiver $receiver){
    $receiver->method1()->shouldBeCalled();
    $receiver->method2()->shouldBeCalled();
    $this->call();
}

我的问题是,每次测试都会膨胀。在这个例子中,它只是一个额外的行,但想象一个方法,它用很多 setter 构建一个对象。 我需要为每个测试编写所有设置器。很难看出测试的目的,因为每个测试都很大并且看起来都一样。

我很确定这不是 phpspec 或 bdd 的问题,而是我的架构的问题。写这个更好(更可测试)的方法是什么?

例如:

public function handleRequest($request, $endpoint){
    $endpoint->setRequest($request);
    $endpoint->validate();
    $endpoint->handle();
}

在这里,我验证请求是否为特定端点提供了所有必要的信息(或抛出异常),然后处理该请求。我选择这种模式来将验证与端点逻辑分开。

【问题讨论】:

    标签: php testing bdd phpspec


    【解决方案1】:

    ProphecyPhpSpec 使用的 mocking 框架,很有主见。它遵循 mockist 方法(伦敦 TDD 学院),它主张我们应该一次描述一种行为。

    模拟是一种测试,因此您希望每次测试保留一个模拟。你可以模拟所有的调用,但这看起来并不优雅。推荐的方法是分离您正在测试的行为并选择该行为所需的模拟,对其余的调用进行存根。如果您发现自己在一项测试中创建了大量存根,这表明功能嫉妒——您应该考虑将行为转移到被调用者,或者在中间添加一个人。

    假设您决定继续描述您拥有的代码,而不进行重构。如果您对第二个呼叫感兴趣,根据您的示例,您应该使用 willReturn 或类似方法对其他呼叫进行存根。例如。 $endpoint->setRequest(Argument::type(Request::class))->willReturn() 而不是 shouldBeCalled()

    【讨论】:

    • 我完全明白你的观点 Marcello 但我还没有:当我将行为转移到被调用者时,我会失去控制。在示例中,我故意拆分了 validate() 和 handle()。这样,无论是哪个开发人员编写的,所有端点的外观和感觉都是一样的。仅使用 $endpoint->handleRequest($request) 之类的一种方法,测试起来会更容易、更干净,但每个人都可以在端点内做他们想做的事。如果我在中间介绍一个人,我只是将我的问题转移到另一个班级。
    • 预言不会阻止你,但你必须引入存根。气味只是表明出现问题 - 就像检查引擎灯一样。由我们决定是否以及何时需要我们关注这个问题。
    猜你喜欢
    • 2014-05-29
    • 1970-01-01
    • 2016-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多