PHPUnit:如何模拟今天的日期而不将其作为参数传递?

And*_*rew 12 phpunit unit-testing

我正在我班上测试一个做日期检查的方法.问题是该方法取决于今天的日期(每天都在变化),这使得这很难测试.我如何模仿今天的日期,以便我的测试明天仍然通过?

Jon*_*eet 8

我对PHP一无所知,但是在Java和C#中我会传递一些描述的"时钟" - 不是今天的日期本身,而是一个可以询问当前日期/时间的对象.然后在单元测试中,您可以传入一个对象,该对象可以提供您想要的任何日期 - 包括一个硬编码到测试中的日期.

这也适用于PHP吗?

  • 是的,不幸的是,这意味着用一个必须在任何地方注入的对象替换轻量函数`date()`.这是正确的方法,但如果没有像Spring Framework这样的好容器,那就很多了. (2认同)

Mik*_*man 6

如果您不想传递保留外部接口的日期,那么执行此操作的好方法是使用"seam"来提供日期:

class MyClass {
  public function toBeTested() {
    $theDate = $this->getDate();
    ...
  }

  protected function getDate() {
    return date();
  }
}
Run Code Online (Sandbox Code Playgroud)

在一般使用中,这个类正常工作.然后,在单元测试中,不是测试MyClass,而是使用覆盖getDate()函数的内部类扩展MyClass:

class MyTest extends phpunittestcase (sorry, writing this freeform, syntax is not exact!!) {

  static $testDate;

  public function testToBeTested() {
    //set the date to be used
    MyTest::testDate = '1/2/2000';
    $classUnderTest = new MyClassWithDate();
    $this->assertEquals('expected', $classUnderTest->toBeTested());

  }

  //just pass back the expected date
  class MyClassWithDate extends MyClass {
    protected function getDate() {
      return MyTest::testDate;
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

在此代码中,您将测试您的真实类的扩展,但您的扩展会覆盖seam函数(getDate()),并返回您要用于此特定测试的日期.

再次,抱歉,如果有一些令人震惊的语法错误,这是徒手写的.