PHP 单元模拟对象类型

PHP Unit mocked objects types

为模拟对象设置类型的正确方法是什么?

示例代码:

/**
 * @dataProvider getTestDataProvider
 * @throws Exception
 */
public function testExampleData(
    Request $request,
    Response $expected,
    SomeClass $someClassMock
): void {
    $result = $someClassMock->getData($request);

    $this->assertEquals($expected, $result);
}

在此示例中,$someClassMock 的类型为 class SomeClass。还有一种名为 MockObject 的类型也可以正常工作,但它会扰乱 class.

中函数的自动完成

我应该在这些模拟对象上使用哪些类型?实物 class 或 MockObject?

为了确保自动完成对模拟的 class 和 MockObject 有效,我所做的是告诉 php 它可以是 class。这为两者添加了自动完成功能,并且让任何阅读代码的人都可以理解它是模拟的以及它模拟的是什么对象。

在你的情况下它看起来像这样:

/**
 * @dataProvider getTestDataProvider
 * @throws Exception
 */
public function testExampleData(
    Request $request,
    Response $expected,
    SomeClass|MockObject $someClassMock // <-- Change made here
): void {
    $result = $someClassMock->getData($request);

    $this->assertEquals($expected, $result);
}

您仍将传递 MockObject,但您的 IDE 不会抱怨任何未知函数。

编辑:为了使其与 8 之前的 PHP 版本一起使用,我建议这样(最小示例):

class ExampleTest extends TestCase 
{
    private someClass | MockObject $someClassMock;

    public function setUp(): void
    {
        $this->someClassMock = $this->createMock(SomeClass::Class);
    }

    public function testMe()
    {
        $this->someClassMock->expects($this->once())->method('getData')->willReturn('someStuff');
    }
}


在这种情况下,变量 $someClassMock 被声明为两种类型,您可以在整个测试过程中使用它,并为它们自动完成。这也应该适用于您的数据提供者,尽管您可能需要稍微重写它。为了简单起见,我没有将它包含在示例中。