Php 为引用time()的方法编写测试
我刚开始使用PHPUnit进行单元测试,我正在使用一些简单的方法来了解它。一个例子立即令人费解: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
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);