我是 php 单元测试的新手。如何在下面的函数中模拟日期。目前它正在获取当前日期。但我想将模拟中的日期更改为一个月的第一天。
function changeStartEndDate() {
if (date('j', strtotime("now")) === '1') {
$this->startDate = date("Y-n-j", strtotime("first day of previous month"));
$this->endDate = date("Y-n-j", strtotime("last day of previous month")) . ')';
} else {
$this->startDate = date("Y-n-j", strtotime(date("Y-m-01")));
$this->endDate = date("Y-n-j", strtotime("yesterday"));
}
}
Run Code Online (Sandbox Code Playgroud)
我试过这样做,但它不起作用。
public function testServicesChangeStartEndDate() {
$mock = $this->getMockBuilder('CoreFunctions')
->setMethods(array('changeStartEndDate'))
->getMock();
$mock->method('changeStartEndDate')
->with(date("Y-n-j", strtotime(date("Y-m-01"))));
$this->assertSame(
'1',
$this->core->changeStartEndDate()
);
}
Run Code Online (Sandbox Code Playgroud)
通过避免副作用,单元测试效果最好。双方date并strtotime都取决于你的主机系统,即当前时间上定义的外部状态。
解决这个问题的一种方法是使当前时间成为可注入的属性,允许您“冻结”它或将其设置为特定值。
如果您查看strtotime它的定义,它允许设置当前时间:
strtotime ( string $time [, int $now = time() ] ) : int
Run Code Online (Sandbox Code Playgroud)
同date:
date ( string $format [, int $timestamp = time() ] ) : string
Run Code Online (Sandbox Code Playgroud)
因此,始终从您的函数中注入该值,以将代码结果与主机状态分离。
function changeStartEndDate($now) {
if (date('j', strtotime("now", $now), $now) === '1') {
...
$this->startDate = date("Y-n-j", strtotime(date("Y-m-01", $now), $now));
$this->endDate = date("Y-n-j", strtotime("yesterday", $now), $now);
}
Run Code Online (Sandbox Code Playgroud)
你的函数是类的一部分吗?然后我会制作$now构造函数的一部分,并将其默认为time(). 在你的测试用例中,你总是可以注入一个固定的数字,它总是会返回相同的输出。
class MyClassDealingWithTime {
private $now;
public function __construct($now = time()) {
$this->now = $now;
}
private customDate($format) {
return date($format, $this->now);
}
private customStringToTime($timeSring) {
return strtotime($timeStrimg, $this->now);
}
}
Run Code Online (Sandbox Code Playgroud)
在您的测试用例中,您然后将 $now 设置为您需要的值,例如通过
$firstDayOfAMonth = (new DateTime('2017-06-01'))->getTimestamp();
$testInstance = new MyClassDealingWithTime(firstDayOfAMonth);
$actual = $testInstance->publicMethodYouWantTotest();
...
Run Code Online (Sandbox Code Playgroud)