dongqiu3254 2016-10-28 10:16
浏览 44
已采纳

模拟包装时间函数

I have a created a minor wrapper function for the php time() method in my class

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();
    }
}

I want to test the public function myFunction() in this class but I am at a bit of a loss how I can mock the currentTime method without mocking the SUT itself (MyClass)

What is the correct way of doing this? I felt creating a time class with a single method (getCurrentTime) and injecting it into MyClass while correct, was excessive as I only check the time in one place in my code.

Is this the best method regardless?

EDIT: I am considering making a time trait as it looks like PhpUnit can mock this. Still unsure if this is overkill for use in a single method..

What other options do I have?

  • 写回答

2条回答 默认 最新

  • dongliulu1122 2016-10-28 11:45
    关注

    You can create a Partial mock object of your tested class in order to modify the behaviour only of the selected method (the currentTime method). For this purpose you can use the setMethods of the Mock Builder API:

    setMethods(array $methods) can be called on the Mock Builder object to specify the methods that are to be replaced with a configurable test double. The behavior of the other methods is not changed. If you call setMethods(NULL), then no methods will be replaced.

    So try this code (suppose the myFunction return the result of the isPending method):

    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()));
        }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 Python报错怎么解决
  • ¥15 simulink如何调用DLL文件
  • ¥15 关于用pyqt6的项目开发该怎么把前段后端和业务层分离
  • ¥30 线性代数的问题,我真的忘了线代的知识了
  • ¥15 有谁能够把华为matebook e 高通骁龙850刷成安卓系统,或者安装安卓系统
  • ¥188 需要修改一个工具,懂得汇编的人来。
  • ¥15 livecharts wpf piechart 属性
  • ¥20 数学建模,尽量用matlab回答,论文格式
  • ¥15 昨天挂载了一下u盘,然后拔了
  • ¥30 win from 窗口最大最小化,控件放大缩小,闪烁问题