Php 模拟包装器时间函数

Php 模拟包装器时间函数,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

我已经为类中的php
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()));
    }