如何根据参数从模拟对象返回不同的值

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

我想模拟redis服务器的返回值。根据密钥我需要取回不同的假值。 由于这仍然很容易,我希望将硬盘上文件的内容作为返回值,因此我可以使用不同的假输入来改变模拟。这是为了测试自定义身份验证以创建不同的复杂用户权限。

我目前正在使用 phpunit 9,很快就会升级到 phphunit 10,所以我想避免使用已弃用的方法,例如

at
withConsecutive

我认为回调函数应该能够实现这一点,但我似乎没有做对。

    private function mockAuthRedisService(
        string $authFile = 'auth_admin',
        string $userGlobalsFile = 'user_globals_admin'
    ): MockObject|AuthRedisServiceInterface {
        $authJson = $this->readfile($authFile);
        $userGlobalsJson = $this->readfile($userGlobalsFile);

        $redisService = $this->getMockBuilder(AuthRedisServiceInterface::class)
                             ->disableOriginalConstructor()
                             ->getMock();


        $redisService->expects($this->any())
         ->method('getAuthData')
            ->will(
                $this->returnCallback(
                    function(string $keyName) {
                        if (strstr($keyName, 'authInfo')) return $authJson;
                        if (strstr($keyName, 'userGlobals')) return $userGlobalsJson;
                    }
                )
            );

        return $redisService;
    }



    private function readfile(string $name): string
    {
        $path = __DIR__ . '/Unit/Security/test_data_files/' . $name . '.json';

        return file_get_contents($path);
    }

因此,为了进行身份验证,我需要从“redis 服务器”读取两个不同的文件,并且它们都有一个复杂的 json 结构,这就是我从磁盘读取它们的原因。

根据不同的测试我想使用不同的输入文件。

因此,在实际使用中,我使用不同的字符串调用方法“getAuthData”,并根据字符串我得到不同的数据。

如何实现使用不同输入文件进行模拟的灵活性?

当前的设置给了我

TypeError: Mock_AuthRedisServiceInterface_4131c2db::getAuthData(): Return value must be of type string, null returned
这并不奇怪,因为包含文件内容的两个变量不在回调函数中,我需要了解这两个变量的数据如何在回调函数或替代解决方案中可用。

我已经看过这些问题:

[1]PHPunit 模拟对象并根据对象属性值对连续调用进行不同的响应

[2]PHPUnit 每次调用模拟方法的返回值不同

[3]如何让 PHPUnit MockObjects 根据参数返回不同的值? 和其他一些人并尝试调整解决方案,但它不适合我的目的。

unit-testing mocking phpunit closures
1个回答
0
投票

我现在所做的是以下内容,这只是可能的,因为我知道需要数据的顺序。所以这并不是解决一般问题的方法,我很幸运它对我有用。 代码是这样的:

    private function mockAuthRedisService(
        string $authFile = 'auth_admin',
        string $userGlobalsFile = 'user_globals_admin'
    ): MockObject|AuthRedisServiceInterface {
        $authJson = $this->readfile($authFile);
        $userGlobalsJson = $this->readfile($userGlobalsFile);

        $redisService = $this->getMockBuilder(AuthRedisServiceInterface::class)
                             ->disableOriginalConstructor()
                             ->getMock();

        $redisService->expects($this->exactly(3))
                     ->method('getAuthData')
                     ->will($this->onConsecutiveCalls($authJson, $authJson, $userGlobalsJson));

        return $redisService;
    }

    private function readfile(string $name): string
    {
        $path = __DIR__ . '/Unit/Security/acs_answers/' . $name . '.json';

        return file_get_contents($path);
    }

所以我只是告诉代码在前两次调用时返回 $authJson,在第三次调用时返回 $userGlobalsJson。这不是我想要的灵活性,所以如果有人有更好的想法,仍然欢迎!

© www.soinside.com 2019 - 2024. All rights reserved.