使用模拟的 PHPUnit 测试无法拦截模拟类上的方法调用

问题描述 投票:0回答:1

这是我的 PHPUnit 测试(PHPUnit 10.5.2 Mockery 1.6.11)

    public function testMergedDocumentsWithSuccessfulInit() {
        $params = new \Buan\Request\Parameters([], [], [], []);
        $mockAdminView = m::mock(AdminView::class);

        // The mocking of init method will consider the inheritance from Ias\AdminController.
        $controller = m::mock('DocumentsController', [$params])
            ->makePartial()
            ->shouldAllowMockingProtectedMethods();

        // Mock the 'init' method which is inherited from Ias\AdminController
        $controller->shouldReceive('init')
            ->with($mockAdminView)
            ->andReturn(true)
            ->once(); // Ensure the init method is mocked to return true once

        echo "Mock setup complete, testing init call\n";
        $initResult = $controller->init($mockAdminView); // This should print true as the init method is mocked
        echo "init called, result: " . ($initResult ? "true" : "false") . "\n";

        // Execute the mergedDocuments method and check the result
        $result = $controller->mergedDocuments();

这是我在 DocumentsController 上测试的方法的开始:

    public function mergedDocuments(): AdminView
    {
        // Init
        $view = new AdminView();
        $initResult = $this->init($view);
        if (!$initResult) {
            return $view;
        }

“init”方法在 DeveloperController 扩展的 AdminController 中定义,例如

class DocumentsController extends Ias\AdminController

DocumentsController 位于全局命名空间中,而 AdminController 位于 Ias 中(不确定这是否相关)。

无论我将“->andReturn(...)”设置为什么,总是会达到返回 $view,即“init”方法不会被拦截并正常运行,始终返回 false。

protected function init(AdminView $view, bool $bypassAuthCheck = false): bool

我的问题是,为什么init方法没有被拦截?

我期望通过将“andReturn”设置为 false,在我的 mergeDocuments 方法中不会达到早期返回。

php testing phpunit mockery
1个回答
0
投票

我在 IDE 中注意到,当我将鼠标悬停在“init”函数上时,它显示:“成员具有受保护的可见性,但可以访问“__call”魔术调用方法”。我按如下方式更新了我的测试,这有效:

    public function MergedDocumentsWithFailedInit()
{
    $params = new \Buan\Request\Parameters([], [], [], []);

    // Since DocumentsController extends Ias\AdminController, create a mock of DocumentsController.
    // The mocking of init method will consider the inheritance from Ias\AdminController.
    $controller = m::mock('DocumentsController', [$params])
        ->makePartial()
        ->shouldAllowMockingProtectedMethods();

    // Mock the behavior of the __call method to delegate calls to init
    $controller->shouldReceive('__call')
        ->with('init', m::on(function ($args) {
            return count($args) == 1 && $args[0] instanceof AdminView;
        }))
        ->andReturnUsing(function ($method, $args) use ($controller) {
            return $controller->init(...$args);
        });

    // Mock the behavior of the init method to always return true
    $controller->shouldReceive('init')
        ->andReturn(false);

    $initResult = $controller->init($mockAdminView);

    // Execute the mergedDocuments method and check the result
    $result = $controller->mergedDocuments();
    $this->assertInstanceOf(AdminView::class, $result);
}
© www.soinside.com 2019 - 2024. All rights reserved.