1

我正在尝试开始使用 PHPSpec,但我碰壁了。为了在我被赋予使用的现有代码中模拟正确的东西,事情变得有点复杂,但本质上我的问题涉及测试在刚刚创建的对象上发生的事情。

我有RepositoryFactory一个createRepository(EntityManager $em, $entityName)

DoctrineEntityManager::getRepository($entityName)只是调用RepositoryFactory::getRepository(EntityManager $em, $entityName),如果存储库不存在,那调用RepositoryFactory::createRepository(EntityManager $em, $entityName)

因此,在我的测试中,存储库是从RepositoryFactory::getRepository.

class MyEntityManagerSpec extends ObjectBehavior
{
    function let(..., MyRepositoryFactory $rfact, MyEntityRepository $repo, ...)
    {
        ....

        $rfact->getRepository(Argument::any(), Argument::any())
              ->willReturn($repo);

        ...
    }

    function it_sets_a_field_on_repositories(MyEntityRepository $repo)
    {
        //This class calls its own getRepository, which calls 
        //getRepository on the factory, which ->willReturn($repo).
        //So, effectively (but without mocking the SUT) that means
        //$this->getRepository($entityName)->willReturn($repo)

        $entityName = 'blah\blah\FakeEntity';

        $repo->setField(Argument::any())->shouldBeCalled(); 
        //The above fails with 
        //"No calls that match MyEntityRepository\P112->setField(*)"

        $gotRepo = $this->getRepository($entityName);

        $repo->setField(Argument::any())->shouldHaveBeenCalled();
        //This fails in the same way

        $gotRepo->shouldBe($repo);
        //This test passes but doesn't let me verify the property was set
        //and is therefore of little help to me

        $gotRepo->getField()->shouldNotBeNull();
        //I wanted to use shouldBe/shouldHaveBeenCalled but if the field's
        //been set that's just as good. Except this fails as well, with
        //"is_null(null) not expected to return true, but it did."
    }

现在,在孤立测试的答案开始出现之前,我意识到了这一点。我首先开始尝试编写对字段设置的检查,MyRepositoryFactory::createRepository但出现了同样的问题——如果我在 中制作对象createRepository,那么我没有可以使用 shouldBe/shouldHaveBeenCalled 进行测试的模拟。但是我正在尝试在这里做正确的事情,所以如果这是我测试的错误地方,我宁愿重构很多而不是通过一个hacky测试。

编辑:这是正在测试的实际位

class MyEntityManager
{
    ...

    public function getRepository($entityName)
    {
        $repo = parent::getRepository($entityName);

        $metaData = $this->getClassMetadata($entityName);

        $flag = $this->getTarget() && $metaData->reflClass
            ->implementsInterface('Caj\Bundle\NameOfBundle\Model\NameOfBundleInterface');

        if($flag) {
            $repo->setField($this->getField());
        }
        return $repo;
    }
}

上面的 $repo 应该在这里被嘲笑;parent::getRepository==> RepositoryFactory::getRepository==>RepositoryFactory::createRepository

此外,我知道测试进入了if($flag)块,但里面的代码不起作用。$this->getField()正常工作并返回,但$repo->setField仍收到 null。$repo->setField($field)是一个没有时髦逻辑的普通二传手。

4

0 回答 0