1

我正在尝试使用 Atoum 设计一个 Database($db) Mock,它会根据以前的方法调用(和参数)返回不同的值。

我正在使用 PHP 5.6 和 Atoum 3.2

这是我尝试过的:

$this->calling($db)->select = function($table, array $bind, $boolOperator = "AND") use ($permissionClientMapper, $db, $permissionsClientRaw){
    if($table === $permissionClientMapper->getTableName()){
        $this->calling($db)->fetchAll = function() use ($bind, $permissionsClientRaw){
            if(array_key_exists('type_service', $bind) && array_key_exists('id_service', $bind) && $bind['type_service'] === 'mutu' && $bind['id_service'] === 4012){
                return EXPECTED_RETURN_VALUE;
            }
            return null;
        };
    }
};

我会在调用时返回代码EXECTED_RETURN_VALUE(带参数):

1/ $db->select() -> This method is called as expected
2/ $db->fetchAll() -> This one is never called

我在 Atoum 文档中没有找到任何这样的例子。

有人可以确认这是模拟连续方法调用的正确方法吗?

我还尝试在闭包中使用对数据库的引用

$this->calling($db)->select = function($table, array $bind, $boolOperator = "AND") use ($permissionClientMapper, &$db, $permissionsClientRaw){
    if($table === $permissionClientMapper->getTableName()){
        $this->calling($db)->fetchAll = function() use ($bind, $permissionsClientRaw){
            if(array_key_exists('type_service', $bind) && array_key_exists('id_service', $bind) && $bind['type_service'] === 'mutu' && $bind['id_service'] === 4012){
                return EXPECTED_RETURN_VALUE;
            }
            return null;
        };
    }
};

但这也不起作用。

编辑:一种解决方法可能是使用 atoum 调用顺序为每个调用返回不同的值,然后测试模拟以检查它是否使用正确的参数调用。

4

1 回答 1

3

我会给你一些关于你的问题的见解,并希望能给你一些线索来找到解决它的方法。

所以要验证一个模拟方法没有被调用,你可以使用'call'和'never'

$this->mock($mock)->call('fetchAll')->never();

并被称为:

$this->mock($mock)->call('select')->once();

为了处理你的模拟答案,你可以使用几个东西,像这样

$this->calling($db)->fetchAll[0] = null; // default answer
$this->calling($db)->fetchAll[1] = function () {....} // first call to method

如果您想要类似链的东西:当使用模拟方法 select 时,我们在其中调用 fetchAll 方法,那么答案是...... atoum 还没有提供这种行为。最好的办法是创建一个暴露您的案例的问题。

当您使用“调用”时,您定义了模拟的行为。只有当方法被调用时,atoum 才会抓住一切并解决它。

所以对我来说,如果我理解正确你的问题,我会这样写:

$this->calling($db)->fetchAll = function() use ($bind){
            if(array_key_exists('type_service', $bind) && array_key_exists('id_service', $bind) && $bind['type_service'] === 'mutu' && $bind['id_service'] === 4012){
                return EXPECTED_RETURN_VALUE;
            }
            return null;
        };
$this->calling($db)->select = function($table, array $bind, $boolOperator = "AND") use ($permissionClientMapper, $db){
    if($table === $permissionClientMapper->getTableName()){
        return $db->fetchAll();
    }
};
// this is the same as your code. But It a bit more readable

$this->newTestedInstance;
$this->testedInstance->setDb($db);
$this->variable($this->testedInstance->doTheCallThatReturnNull())
    ->isEqualTo(null);
// do some change in the vars to be in the value
$this->variable($this->testedInstance->doTheCallThatReturnValue())
    ->isEqualTo(EXPECTED_RETURN_VALUE);

ps:为了帮助您更进一步,您可以阅读http://docs.atoum.org/en/latest/asserters.html#mockhttp://docs.atoum.org/en/latest/mocking_systems.html ,您可以还用“atoum”标记问题。

于 2017-11-28T15:50:53.320 回答