我有一个类:
class Foo {
function getCurrentBar() {
$model = Query::findByPk($this->getSession()->get('current_bar')); // Pseudocode...
return $model;
}
}
所以基本上我的应用程序中一次只有一个栏,它作为整数存储在会话中。我经常调用一个辅助函数来查找模型实例,它会进行数据库查询。还有缓存,但现在没关系。
我的问题是:我如何用对进行单元测试?我测试的类需要这个。我想我可以改变会话以包含id但是这意味着我需要在数据库中有相应的模型。
最佳方法是仅为单元测试添加方法setCurrentBar()
吗?然后我可以模拟一个条形对象并设置它,它将用于所有单元测试。这有意义吗?
答案 0 :(得分:6)
答案确实是依赖注入,但你想要控制的依赖是吧的源,而不是吧本身。
class Foo {
private $query;
function __construct($query)
{
$this->query = $query;
}
function getCurrentBar() {
$model = $this->query->findByPk($this->getSession()->get('current_bar')); // Pseudocode...
return $model;
}
}
所以在你的生产代码中你有
$query = new Query() // assuming findByPk() is made a normal non-static method
$realFoo = new Foo($query);
但是对于单元测试...
$testFoo = new Foo(new MockQuery());
其中MockQuery
是Query
类的模拟版本,它返回mock bars 。
答案 1 :(得分:0)
您可以尝试使用dependency injection。
将Bar实例传递给Foo构造函数
class Foo
{
private _bar;
function __construct (Bar $bar)
{
$this->_bar = $bar;
}
public function getCurrentBar()
{
return $this->_bar;
}
}
然后,您可以在运行测试时注入模拟Bar对象。
答案 2 :(得分:0)
您也可以选择测试部分模拟对象,直到DI系统到位为止。
class Foo {
function getCurrentBar() {
$model = $this->getQueryResult($this->getSession()->get('current_bar')); // Pseudocode...
return $model;
}
function getQueryResult($queryParams)
{
return Query::findByPk($queryParams);
}
}
然后做一个看起来有点像这样的测试...
$myObjectToTest = $this->getMock('Foo', array('getQueryResult'), array(), '', true, true, true);
$myObjectToTest->expects($this->once())
->method('getQueryResult')
->with($whateverTheQueryParametersAre)
->will($this->returnValue($someResult));
$myObjectToTest->getCurrentBar();