2

我刚刚开始使用 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);
}
4

2 回答 2

2

将时间相关代码提取到单独的类是最佳选择。

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

在 php 中,您必须使用 DateTime 的替代品,例如来自ouzo goodies的Clock

然后在你的代码中使用:

$time = Clock::now();

在您的测试中:

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

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

//then
$this->assertEquals('2011-01-02', $result);
于 2015-01-07T18:34:26.473 回答
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() 函数。这样,您可以在即将调用 setDelay 的代码中使用 time(),并将其传递给类,或者如果缺少它,则允许该类在运行时创建它。但是,对于您的测试,您始终将时间设置为已知值,而不是 time()。

$currentTime = DateTime::createfromformat('hms', '100000');    
于 2012-11-22T19:12:11.567 回答