34

我在测试中有一个模拟对象。真正的对象 PageRepository 使用 __call() 实现了一个神奇的方法,因此如果您调用 $pageRepository->findOneByXXXX($value_of_field_XXXX),它将在数据库中搜索与该参数匹配的记录。

有没有办法模拟该方法?

真正的方法调用看起来像这样:

$homepage = $pageRepository->findOneBySlug('homepage');

测试看起来像这样:

$mockPageRepository->expects($this->any())
    ->method('findOneBySlug')
    ->will($this->returnValue(new Page()));

但它不起作用—— PHPUnit 没有发现方法调用。让它看到该方法的唯一方法是在 PageRepository 中显式定义该方法。

4

2 回答 2

47

PHPUnitgetMock()接受第二个参数,一个包含要模拟的方法名称的数组。如果您在此数组中包含方法名称,则模拟对象将包含具有该名称的方法,expects()并且朋友将使用该方法。

这甚至适用于未在“真实”类中定义的方法,因此类似以下内容应该可以解决问题:

$mockPageRepository = $this->getMock('PageRepository', array('findOneBySlug'));

请记住,您必须明确包含任何其他也需要模拟的方法,因为只有数组中命名的方法是为模拟对象定义的。

于 2011-06-02T05:27:56.667 回答
3

我找到了更好的方法来做到这一点。仍然不完美,但您不必手动指定所有模拟类方法,只需指定魔术方法:

    $methods = get_class_methods(PageRepository::class);
    $methods[] = 'findOneBySlug';
    $pageRepositoryMock = $this->getMockBuilder(PageRepository::class)
        ->disableOriginalConstructor()
        ->disableOriginalClone()
        ->disableArgumentCloning()
        ->disallowMockingUnknownTypes()
        ->setMethods($methods)
        ->getMock();
于 2019-12-19T13:53:22.353 回答