我刚开始使用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 :(得分:2)
将时间相关代码提取到单独的类是最佳选择。
然而,有时似乎有点矫枉过正。在其他语言中,可以全局设置时间,例如DateTimeUtils.setCurrentMillisFixed in java或delorean in ruby。
在php中你必须使用DateTime的替代品,例如来自Clock
的ouzo goodies然后在你的代码中使用:
$time = Clock::now();
在你的测试中:
//given
Clock::freeze('2011-01-02 12:34');
//when
$result = YourCode::doSomethingWithTimeReturnedByClockNow();
//then
$this->assertEquals('2011-01-02', $result);
答案 1 :(得分:1)
基本上,您需要按照您的预期测试功能,并根据您的示例提出一些小挑战。第一个简单的测试是在代码发送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()函数。这样,您可以在代码中使用time()来调用setDelay,并将其传递给类,或者如果缺少类,则允许类在运行时创建它。但是,对于您进行测试,您始终将时间设置为已知值,而不是时间()。
$currentTime = DateTime::createfromformat('hms', '100000');