PHPUnit强迫我模拟实体



让我们考虑一下这个场景

public class FooManager()
{
    //somewhere in my manager class code
    public function merge(Foo $a, Foo $b, $id)
    {
        if ($a->getId() == $id) { //!! PAY ATTENTION !!
        }
        //and so on
    }
}

我在很多地方都读到模拟实体不是一个好的实践,但是我想知道这段特定的代码。

如果我不能给一个真实的实体对象分配一个Id(例如,它是根据原则自动生成的),我如何在不模拟Foo实体的情况下测试这个功能?

更新

我正在思考这个问题,然后突然闪了一下。在我看来:我在这里测试的是FooManager,而不是实体。因此,对我来说,使用mock不是唯一的解决方案,但可能是最好的解决方案。有人能帮我理解一下我的思维过程是不是很好?

更新2

我之前没有提到过,但是,当然,我需要测试$a$b的变化($a将从$b接收一些属性值,并将相应地更新其属性)。这是测试的目标,因为FooManager的目标是将$b属性合并到$a属性中(当然要应用一些逻辑)

如果您需要绕过doctrine的自动生成实体id策略,您可以通过元数据操作,并设置一个已知id。例如,如果你用DoctrineFixtureBundle加载你的测试fixture,你可以在你的fixture中有:

class FooFixtures  extends AbstractFixture implements OrderedFixtureInterface
{
    public function load(ObjectManager $manager)
    {
        $metadata = $manager->getClassMetaData("Acme\DemoBunde\Entity\Foo");
        $metadata->setIdGeneratorType(DoctrineORMMappingClassMetadata::GENERATOR_TYPE_NONE);
...        
        $foo = new Foo();
        $foo ->setId(3);
        $foo ->setTitle('Foo example');
然后在测试类 中使用它
public function setUp()
{
    parent::setUp();
    $this->fooFixtures = new FooFixtures();
    $this->loadFixtures(array($this->fooFixtures));
 }

现在数据库中有一个id为3的Foo实例

希望这对你有帮助,我理解你的需要

免责声明:使用数据库id!!!!硬编码测试不是一个好做法

我的手。

我的第一个想法,正如我前面所说的,是创建一个mock,因为phpspec +原则似乎迫使我这样做。

过了一会儿,然而,我遇到了一个混乱的- >getFoo()->hasToBeCalled(), ->setFoo()->hasToBeCalled()序列,其中FooManager"触摸"的所有属性都需要一个期望。这迫使我重新考虑这个解决方案,不,对我来说不是最好的。

我已经检查了我的类,事实是SUT不是我想在这里直接测试的,但我需要检查的是这个动作对实体的影响(无论如何是一种行为,对吗?),我决定按如下步骤进行:

  • 创建TestFoo实体(在specfolderToMySpecFooSpec.php内部)

    class TestFoo extends Foo
    {
        public function setId($id) 
        {
            $this->id = $id
        }
    }
    

    这样我就可以直接设置$id(不是我需要测试的行为作为学说,在正常情况下会为我做),并保持这个类在我的/src代码库之外

  • 我已经修改了我的merge()函数,只返回我需要检查测试目的的实体(而且,不,我不只是为了测试的缘故,因为有一些关于合并实体的信息可能是有用的)

  • 最后,使用直接从SUT返回的这个实体,我可以像通常使用SUT本身一样使用预言匹配器。

这个解决方案有很多优点,因为我不需要编写每个将被模拟实体调用的方法,并且让我可以自由地使用返回的存根只测试我真正需要测试的内容。

任何想法吗?

如果您需要为写测试创建mock,那么创建它是正常的。

在这种具体情况下,您需要存根。我推荐阅读这篇可爱的文章来解释mock和mock之间的区别。存根。

Robert C. Martin说:模拟跨架构上重要的边界,但不能在这些边界内模拟。你可以从这一点入手进行研究。

和我的意见:因为在这种情况下,你需要创建一个模拟写正确的测试-创建它。我看不出这有什么不好。

相关内容

  • 没有找到相关文章

最新更新