上面的大多数答案都表明,模拟随机数生成器是可行的方法,但是我只是使用内置的mt_rand函数。允许模拟将意味着重写类以要求在构造时注入随机数生成器。
还是我想!
添加名称空间的后果之一是,PHP函数内置的模拟已经从难以置信变成了极其简单。如果SUT在给定的名称空间中,那么您要做的就是在该名称空间下的单元测试中定义您自己的mt_rand函数,并且在测试期间将使用它代替内置的PHP函数。
这是最终的测试套件:
namespace gordian\reefknot\util;
/**
* The following function will take the place of mt_rand for the duration of
* the test. It always returns the number exactly half way between the min
* and the max.
*/
function mt_rand ($min = 42, $max = NULL)
{
$min = intval ($min);
$max = intval ($max);
$max = $max < $min? $min: $max;
$ret = round (($max - $min) / 2) + $min;
//fwrite (STDOUT, PHP_EOL . PHP_EOL . $ret . PHP_EOL . PHP_EOL);
return ($ret);
}
/**
* Override the password character pool for the test
*/
class PasswordSubclass extends Password
{
const CHARLIST = 'AAAAAAAAAA';
}
/**
* Test class for Password.
* Generated by PHPUnit on 2011-12-17 at 18:10:33.
*/
class PasswordTest extends \PHPUnit_Framework_TestCase
{
/**
* @var gordian\reefknot\util\Password
*/
protected $object;
const PWMIN = 15;
const PWMAX = 20;
/**
* Sets up the fixture, for example, opens a network connection.
* This method is called before a test is executed.
*/
protected function setUp ()
{
}
/**
* Tears down the fixture, for example, closes a network connection.
* This method is called after a test is executed.
*/
protected function tearDown ()
{
}
public function testGetPassword ()
{
$this -> object = new PasswordSubclass (self::PWMIN, self::PWMAX);
$pw = $this -> object -> getPassword ();
$this -> assertTrue ((bool) preg_match ('/^A{' . self::PWMIN . ',' . self::PWMAX . '}$/', $pw));
$this -> assertTrue (strlen ($pw) >= self::PWMIN);
$this -> assertTrue (strlen ($pw) <= self::PWMAX);
$this -> assertTrue ($pw === $this -> object -> getPassword ());
}
public function testGetPasswordFixedLen ()
{
$this -> object = new PasswordSubclass (self::PWMIN, self::PWMIN);
$pw = $this -> object -> getPassword ();
$this -> assertTrue ($pw === 'AAAAAAAAAAAAAAA');
$this -> assertTrue ($pw === $this -> object -> getPassword ());
}
public function testGetPasswordFixedLen2 ()
{
$this -> object = new PasswordSubclass (self::PWMAX, self::PWMAX);
$pw = $this -> object -> getPassword ();
$this -> assertTrue ($pw === 'AAAAAAAAAAAAAAAAAAAA');
$this -> assertTrue ($pw === $this -> object -> getPassword ());
}
public function testInvalidLenThrowsException ()
{
$exception = NULL;
try
{
$this -> object = new PasswordSubclass (self::PWMAX, self::PWMIN);
}
catch (\Exception $e)
{
$exception = $e;
}
$this -> assertTrue ($exception instanceof \InvalidArgumentException);
}
}
我以为我会提到这一点,因为重写PHP内部函数是对我完全没有想到的命名空间的另一种用法。感谢大家的帮助。