Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/226.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 为引用time()的方法编写测试_Php_Unit Testing_Phpunit - Fatal编程技术网

Php 为引用time()的方法编写测试

Php 为引用time()的方法编写测试,php,unit-testing,phpunit,Php,Unit Testing,Phpunit,我刚开始使用PHPUnit进行单元测试,我正在使用一些简单的方法来了解它。一个例子立即令人费解: function setDelay($seconds) { if($seconds == 0) { $this->delay = 0; } else { $this->delay = time() + $seconds; } } 当time()在方法之外未知时,如何确定正确的预期结果 public func

我刚开始使用PHPUnit进行单元测试,我正在使用一些简单的方法来了解它。一个例子立即令人费解:

function setDelay($seconds)
{
    if($seconds == 0)
    {
        $this->delay = 0;
    }
    else
    {
        $this->delay = time() + $seconds;
    }
}
当time()在方法之外未知时,如何确定正确的预期结果

public function testSetDelayNonZero() {
  $expected = [??];
  $this->class->setDelay(100);
  $actual = $this->class->delay;
  $this->assertEquals($expected, $actual);
}

基本上,您需要像预期的那样测试功能,并根据您的示例进行一些小的挑战。第一个简单的测试是向代码发送0秒。此测试可能与以下内容一样简单:

public function test_setDelay()
{
    this->assertEquals(0, setDelay(0));
}
为了测试时间是否正确向前移动,您可以模拟对象,使延迟始终返回一个设置的时间加上秒,或者使用依赖项注入将时间传递到函数/类中以获得它,这样您就可以设置对象,然后进行调用以确保返回的时间与预期时间相符

public function test_setDelay()
{
    this->assertEquals(0, setDelay(0));

    $setDelayMock = $this->getMock('DelayClass');
    $setDelayMock->method('setDelay')
        ->with($this->equalTo(5))
        ->will($this->returnValue('10:00:05'));
    $this->assertEquals('10:00:05', $setDelayMock->setDelay(5))
}
这实际上并不测试setDelay,但有助于测试它之后的操作。依赖项注入很可能是将时间发送到类的目的,如果不存在依赖项注入,则使用time()函数。这样,您可以在即将调用setDelay的代码中使用time(),并将其传递给类,或者在缺少setDelay的情况下允许类在运行时创建它。但是对于测试,您总是将时间设置为已知值,而不是time()


将依赖于时间的代码提取到单独的类是最好的选择

然而,有时这似乎有点矫枉过正。在其他语言中,可以全局设置时间,例如java或ruby中固定的DateTimeUtils.setCurrentMillisFixed

在php中,您必须使用DateTime的替代品,例如from

然后在代码中使用:

$time = Clock::now();
在您的测试中:

//given
Clock::freeze('2011-01-02 12:34');

//when
$result = YourCode::doSomethingWithTimeReturnedByClockNow();

//then
$this->assertEquals('2011-01-02', $result);

$class->delay
应该是与结果无关的实现细节。你真的需要测试这个属性吗?您不应该测试类的行为,而不是它的属性吗?你为什么一开始就可以进入那处房产?这只是一个例子。如果我确实需要在方法中设置时间的地方测试时间值,我能做到吗?或者,在上面的例子中,如果结果是0或“某物”,我应该只测试0或“某物”而不是特定的值吗?好的,你不应该测试内部状态,你应该测试行为。在使用某个值调用此方法,然后调用其他方法之后,它的行为是否符合预期?不是“在用这个值调用这个方法之后,内部状态是否以我编码它的方式发生了变化?”啊,好的。有些道理。我可能需要继续阅读手册:)把你的对象想象成应该完成一项任务的东西。您可以让他们通过公共接口(方法)完成该任务。您不想测试他们在内部做什么,因为这可能会在任何时候发生变化。您要测试的是它们是否完成了您构建它们的任务。设置内部属性不是需要测试的重要任务。它成功地设置了自己的属性。否,您要测试它是否根据您设置的延迟运行。不知道是否设置了延迟。回答很好,解释得很好。非常感谢。
//given
Clock::freeze('2011-01-02 12:34');

//when
$result = YourCode::doSomethingWithTimeReturnedByClockNow();

//then
$this->assertEquals('2011-01-02', $result);