仅针对某个参数模拟响应

Mocking the response only for a certain parameter

我有一个 class,当用 test1 调用 return 123 时,我正在模拟 get 方法。这很好用。

但是,我希望对 get 方法的所有其他调用 return 通常会被 returned - 即仅具有特定参数的调用 return 是模拟回复。

$configMock = m::mock(Config::class);

$configMock->shouldReceive('get')
        ->with('test1')
        ->andReturn(123);

因此,如果我在代码中使用不同的参数调用 get,即 $config->get('test2'),我会得到错误

Mockery\Exception\NoMatchingExpectationException: No matching handler found for Mockery_1_Illuminate_Contracts_Config_Repository::get("test2"). Either the method was unexpected or its arguments matched no expected argument list for this method

然而,当我在第一行使用 ->makePartial() 时,在第 $config->get('test2') 行出现错误

BadMethodCallException: Method Mockery_1_Illuminate_Contracts_Config_Repository::get() does not exist on this mock object

我如何模拟一个方法响应,只对传递的某个参数进行响应,同时让该方法 return 对该方法的所有其他调用正常响应?

我个人认为应该在每个测试函数中准确指定您希望发生什么。所以基本上就是:

$configMock->shouldReceive('get')
           ->with('test2')
           ->andReturn(INSERT_CORRECT_RESPONSE);

请注意,如果您有很多测试函数执行此操作,这会导致相当多的代码重复,因此您可能希望将其提取到另一个方法中:

private function testCorrectResult($parameter)
{
    $configMock = m::mock(Config::class);

    if ($parameter === 'test1') {
        $configMock->shouldReceive('get')
                   ->with('test1')
                   ->andReturn(123);
    } else {
        $configMock->shouldReceive('get')
                   ->with('test2')
                   ->andReturn(INSERT_CORRECT_RESPONSE);
    }
}

这就是我认为您的问题所在,如果我有错请告诉我!

我最终采纳了@Loeks 的建议。可能有更简洁的方法来执行此操作,但这对我有用。

    $config = new Config;

    $closure = function ($arg) use ($config) {
        switch ($arg) {
            case 'test1':

                return 123;
            default:
                // Return default values

                return $config->get($arg);
        }
    };

    $configMock = m::mock(Config::class)
        ->makePartial();

    $configMock->shouldReceive('get')
        ->andReturnUsing($closure);

您可以多次链接“->shouldReceive('get')”,然后将 >andReturn( 填入您这次真正需要的内容。

您应该避免使用被调用函数的顺序将任何逻辑放入单元测试。