Php,模拟数据库结果集好吗?

时间:2015-07-27 08:27:58

标签: php unit-testing

在我的模特中:

class UsersModel
{
    public function getUsers()
    {
        return SELECT id,username,rights FROM database
    }
}

结果是:

array{
    array{'id' => 1, 'username' => 'a', 'rights' => 4},
    array{'id' => 2, 'username' => 'b', 'rights' => 8},
    array{'id' => 4, 'username' => 'c', 'rights' => 7},
}

然后格式化:

class Helper
{
    function formatUsers (array $source)
    {
        foreach ($source as $item)
        {
             $item['usernameF'] = $item['username'].'.'.$item['id'];
        }
        return $source;
    }
}

结果是:

array{
    array{'id' => 1, 'username' => 'a', 'rights' => 4, 'usernameF' => 'a.1'},
    array{'id' => 2, 'username' => 'b', 'rights' => 8, 'usernameF' => 'b.2'},
    array{'id' => 4, 'username' => 'c', 'rights' => 7, 'usernameF' => 'c.4'}
}

并在视图中输出:

foreach ($users as $item)
{
    echo $item['usernameF'].' = '.$item['rights'].'<br>';
}

到目前为止一直很好,现在让我们测试一下。

testModel:

assertEquals ($result, array{
    array{'id' => 1, 'username' => 'a', 'rights' => 4, 'usernameF' => 'a.1'},
    array{'id' => 2, 'username' => 'b', 'rights' => 8, 'usernameF' => 'b.2'},
    array{'id' => 4, 'username' => 'c', 'rights' => 7, 'usernameF' => 'c.4'}
});

testHelper:

这里遇到了困难。我可以模拟getUsers()方法来强制执行结果。

$mock->setMock ($this->once()->method('getUsers')->willReturn(array{
    array{'id' => 1, 'username' => 'a', 'rights' => 4},
    array{'id' => 2, 'username' => 'b', 'rights' => 8},
    array{'id' => 4, 'username' => 'c', 'rights' => 7}
});

assertEquals ($result, array{
    array{'id' => 1, 'username' => 'a', 'rights' => 4, 'usernameF' => 'a.1'},
    array{'id' => 2, 'username' => 'b', 'rights' => 8, 'usernameF' => 'b.2'},
    array{'id' => 4, 'username' => 'c', 'rights' => 7, 'usernameF' => 'c.4'}
}

但是如果DB方案改变怎么办?如果我不小心输错了字段,请说“usernmame”。结果将是:

array{
    array{'id' => 1, 'usernmame' => 'a', 'rights' => 4},
    array{'id' => 2, 'usernmame' => 'b', 'rights' => 8},
    array{'id' => 4, 'usernmame' => 'c', 'rights' => 7},
}

当然模型测试失败了,所以我也改了:

testModel:

assertEquals ($result, array{
    array{'id' => 1, 'usernmame' => 'a', 'rights' => 4, 'usernameF' => 'a.1'},
    array{'id' => 2, 'usernmame' => 'b', 'rights' => 8, 'usernameF' => 'b.2'},
    array{'id' => 4, 'usernmame' => 'c', 'rights' => 7, 'usernameF' => 'c.4'}
});

所以所有测试都通过 - 但在生产中,视图将以“错误的索引;用户名”失败!那么最好的方法是什么?

1 个答案:

答案 0 :(得分:1)

不要验证超过需要。 formatUsers方法接受数组,除了usernameid之外,它不关心它来自何处,也不关心它具有什么键。在测试此方法时,“模拟”数据是完全正确的。

如果架构发生了变化怎么办?这不是关于您的测试的问题,而是关于您的代码的问题,这是完全有效的问题。良好设计的目标是尽量减少每个变化的范围。在您的情况下,有多个对象知道字段的名称。如果您正在传递具有username属性的对象而不是数组,那么您可以在代码中只有一个位置将DB结果映射到对象,并将DB中使用的名称与名称分离在代码中使用。

顺便说一句,您可以使用array_map代替foreach循环

相关问题