我看到的唯一选择是依赖注入,因为你的类想要使用类之外的资源。因此,这破坏了一些封装规则。
我过去如何做到这一点,是将这些函数放在自己的类中并且要求/包含它们,并且当设置了测试变量时,包含一个具有相同半“模拟”函数的基本文件返回已知状态。
我这样做的另一种方法是创建一个简单的UTILITY类,它包含所有这些数据函数,然后使用依赖注入和mock来进行测试。
class Utilities
{
function doStuff($value)
{
$x = $value + 1;
return $x;
}
}
class MyClass
{
private $UtilitiesObject;
private $field;
public function setMyValue($amount)
{
// $this->field = doStuff($amount) + doStuff(2 * $amount);
$this->field = $this->UtilitiesObject->doStuff($amount) + $this->UtilitiesObject->doStuff(2 * $amount);
}
}
// Constructor Injection, pass the Utilities object here
public function __construct($Utilities = NULL)
{
if(! is_null($Utilities))
{
if($Utilities instanceof Utilities)
{
$this->SetUtilities($Utilities);
}
}
}
function SetUtilities(Utilities $Utilities)
{
$this->UtilitiesObject = $Utilities
}
}
测试:
class UtilitiesTest extends PHPUnit_Framework_TestCase
{
// Could also use dataProvider to send different returnValues, and then check with Asserts.
public function testSetMyValue()
{
// Create a mock for the Utilities class,
// only mock the doStuff() method.
$MockUtilities = $this->getMock('Utilities', array('doStuff'));
// Set up the expectation for the doStuff() method
$MockUtilities->expects($this->any())
->method('doStuff')
->will($this->returnValue(1));
// Create Test Object - Pass our Mock as the Utilities
$TestClass = new MyClass($MockUtilities);
// Or
// $TestClass = new MyClass();
// $TestClass->SetUtilitiess($MockUtilities);
// Test doStuff
$amount = 10; // Could be checked with the Mock functions
$this->assertEquals(2, $TestClass->doStuff($amount)); // Mock always returns 1, so 1+1=2
}
}
看一看http://marcelog.github.io/articles/php_mock_global_functions_for_unit_tests_with_phpunit .html – busypeoples
您是否从任何人获得令人满意的答复以接受,还是仍然存在与这些建议有关的问题? –
@StevenScott其实我决定不再为这个类编写单元测试。太多的屁股疼痛。 –