PHPUnit模拟特征

3
我一直在阅读 PHPUnit 手册,其中有一部分我无法理解,涉及到模拟 traits(图 9.18)。
在他们的例子中,有一个具体的方法返回抽象方法的值(最终在测试中被模拟)。
不幸的是,这两个句子的解释并没有说明其有何用处!就我所知,测试显然会通过,但在实际情况下,抽象方法将不会被模拟,因此它实际上会失败?
我们应该删除抽象方法,并替换掉在具体方法中对其的调用吗?如果是这样,那测试有什么意义呢?为什么我们要用没有被真正使用的抽象方法来混淆 traits 呢?
我的最终问题是,为什么测试在测试中写成可以通过,而如果在实际使用中,它却会失败?如果有人能帮我理解这个问题,我将不胜感激!
1个回答

1
我稍微修改了链接后面的示例,以揭示测试实际上是在测试什么:
<?php
trait AbstractTrait
{
    public function concreteMethod()
    {
        // this is the only logic which is being tested in testConcreteMethod test
        $result = $this->abstractMethod() * 2;

        return $result;
    }

    /**
     * @return int
     */
    public abstract function abstractMethod();
}

class TraitClassTest extends PHPUnit_Framework_TestCase
{
    public function testConcreteMethod()
    {
        $mock = $this->getMockForTrait('AbstractTrait');

        $mock->expects($this->any())
             ->method('abstractMethod')
             ->will($this->returnValue(5));

        $this->assertEquals(10, $mock->concreteMethod());
    }
}

如果AbstractTrait::concreteMethod的实现发生了变化,例如改为
    public function concreteMethod()
    {
        $result = $this->abstractMethod() * 3;

        return $result;
    }

测试将会失败。

说实话,在现实生活中,我从未使用过带有抽象方法的特征,并通过测试使用该特征的类之一来测试特征的逻辑。就像上面的示例一样,如果没有模拟抽象方法,则无法单独测试 AbstractTrait :: concreteMethod


啊,我明白了,这个例子是为了展示特质实际上在现实世界中使用抽象方法?我想我之前有些混淆,认为抽象方法仅仅是为了测试而需要(因此在现实世界中不适用)。谢谢 :) - Phil Cross
我不确定这是否是一个好的实践,想象一下你只测试了这个特性而没有使用它的类,有一天你决定从那个类中删除它...突然间你的代码停止了原来的行为,你不知道为什么,因为你没有在真正的类上进行测试。 因此,当涉及到使用特性功能时,一定要确保测试类的行为。 - itsjavi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接