php - 在 phpspec 中测试多个方法的调用

标签 php testing bdd phpspec

过去我总是偶然发现 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 的对象。 我需要为每个测试编写所有 setter 。很难看出测试的目的,因为每个测试都很大而且看起来都一样。

我很确定这不是 phpspec 或 bdd 的问题,而是我的体系结构的问题。什么是更好(更可测试)的编写方式?

例如:

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

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

最佳答案

Prophecy , PhpSpec 使用的模拟框架,很有主见。它遵循 mockist 方法(TDD 伦敦学院),该方法捍卫我们应该一次描述一种行为。

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

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

关于php - 在 phpspec 中测试多个方法的调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34474097/

相关文章:

PHPWord 模板循环遍历查询结果而不填充值

html - 棱 Angular 分明。从 html 标记中删除属性的构建步骤

ruby - Cucumber hooks可以区分标签吗

oop - 使用 BDD 时遵循开放/封闭原则有什么好处吗?

javascript - HTML 表 - 跟踪表单提交的选择

php - 词典搜索

php - 通过 while 循环插入多行

testing - 使用 gradle 测试时未找到给定的测试包括

http - 如何测试http JSON服务器的性能?

java - 使用不同的基于java的spring上下文配置与cucumber