Php 模拟包装器时间函数
我已经为类中的phpPhp 模拟包装器时间函数,php,unit-testing,testing,phpunit,Php,Unit Testing,Testing,Phpunit,我已经为类中的phptime()方法创建了一个小包装函数 class MyClass { public function myFuncion($unixTimeStamp) { $pending = $this->isPending($unixTimeStamp) // data manipulation return $result } protected function isPending($uni
time()
方法创建了一个小包装函数
class MyClass
{
public function myFuncion($unixTimeStamp)
{
$pending = $this->isPending($unixTimeStamp)
// data manipulation
return $result
}
protected function isPending($unixTimeStamp)
{
if ($unixTimeStamp > $this->currentTime()) {
return true;
}
return false;
}
public function currentTime()
{
return time();
}
}
我想在这个类中测试公共函数myFunction()
,但是我不知道如何在不模拟SUT本身的情况下模拟currentTime方法(MyClass)
正确的做法是什么?我觉得用一个方法(getCurrentTime)创建一个time类,并将它注入MyClass
,虽然正确,但这太过分了,因为我只在代码中的一个地方检查时间
不管怎样,这是最好的方法吗
编辑:我正在考虑制作一个time
特性,因为它不能模仿这个特性。仍然不确定在单一方法中使用该方法是否过度
我还有什么其他选项?我们可以覆盖命名空间级别的
time()
函数。检查
但缺点是每次我们调用time()
它都会返回模拟的时间:)
您可以创建测试类的部分模拟对象,以便仅修改所选方法(
currentTime
方法)的行为。为此,您可以使用的setMethods
:
可以在模拟生成器对象上调用setMethods(数组$methods)以
指定要用可配置测试替换的方法
双重的其他方法的行为不变。如果你打电话
setMethods(NULL),则不会替换任何方法
因此,请尝试以下代码(假设myFunction
返回isPending
方法的结果):
我知道我参加聚会有点晚了,但是如果您能够在您的环境中安装php扩展,您可以使用它,它可以透明地工作,并且对代码进行0次修改。此时,您可以删除
currentTime()
,只需使用time()
我已经决定创建一个类,并在部分模拟SUT的基础上注入它,尽管您的建议有助于解决另一个问题,所以谢谢您
namespace MyClass;
function time()
{
return MyClassTest::$mockTime ?: \time();
}
class MyClassTest extends TestCase{
public static $mockTime;
public function test_my_function(){
self::$mockTime = '08:10';
$myClass = new MyClass();
//$myClass->currentTime() //will return 08:10
//do something with my function
}
class MyClassTest extends \PHPUnit_Framework_TestCase
{
/**
* @test
*/
public function itShouldReturnTrueIfPendingState()
{
$currentTime = (new \DateTime('now -1 year'))->getTimestamp();
/** @var MyClass|\PHPUnit_Framework_MockObject_MockObject $myClass */
$myClass = $this->getMockBuilder(MyClass::class)
->disableOriginalConstructor()
->setMethods(['currentTime'])
->getMock();
$myClass
->method('currentTime')
->willReturn($currentTime);
$this->assertTrue($myClass->myFunction(time()));
}
/**
* @test
*/
public function itShouldReturnFalseIfNotState()
{
$currentTime = (new \DateTime('now +1 year'))->getTimestamp();
/** @var MyClass|\PHPUnit_Framework_MockObject_MockObject $myClass */
$myClass = $this->getMockBuilder(MyClass::class)
->disableOriginalConstructor()
->setMethods(['currentTime'])
->getMock();
$myClass
->method('currentTime')
->willReturn($currentTime);
$this->assertFalse($myClass->myFunction(time()));
}