我为我的班级
中的phptime()
方法创建了一个辅助包装函数
class MyClass
{
public function myFuncion($unixTimeStamp)
{
$pending = $this->isPending($unixTimeStamp)
// data manipulation
return $result
}
protected function isPending($unixTimeStamp)
{
if ($unixTimeStamp > $this->currentTime()) {
return true;
}
return false;
}
public function currentTime()
{
return time();
}
}
我想在这个类中测试公共函数myFunction()
,但是如果我没有模拟SUT本身(MyClass)我可以模拟currentTime方法,我有点遗憾
这样做的正确方法是什么?我觉得使用单个方法(getCurrentTime)创建一个时间类并将其注入MyClass
,但是正确,因为我只检查代码中一个地方的时间。
这是最好的方法吗?
编辑:我正在考虑制作一个time
特征因为looks like PhpUnit可以嘲笑这个。仍然不确定这在单一方法中是否过度使用..
我还有其他选择吗?
答案 0 :(得分:1)
您可以创建测试类的Partial模拟对象,以便仅修改所选方法的行为(currentTime
方法)。为此,您可以使用Mock Builder API的setMethods
:
可以在Mock Builder对象上调用setMethods(array $ methods) 指定要用可配置测试替换的方法 双。其他方法的行为不会改变。如果你打电话 setMethods(NULL),则不会替换任何方法。
请尝试使用此代码(假设myFunction
返回isPending
方法的结果):
class MyClassTest extends \PHPUnit_Framework_TestCase
{
/**
* @test
*/
public function itShouldReturnTrueIfPendingState()
{
$currentTime = (new \DateTime('now -1 year'))->getTimestamp();
/** @var MyClass|\PHPUnit_Framework_MockObject_MockObject $myClass */
$myClass = $this->getMockBuilder(MyClass::class)
->disableOriginalConstructor()
->setMethods(['currentTime'])
->getMock();
$myClass
->method('currentTime')
->willReturn($currentTime);
$this->assertTrue($myClass->myFunction(time()));
}
/**
* @test
*/
public function itShouldReturnFalseIfNotState()
{
$currentTime = (new \DateTime('now +1 year'))->getTimestamp();
/** @var MyClass|\PHPUnit_Framework_MockObject_MockObject $myClass */
$myClass = $this->getMockBuilder(MyClass::class)
->disableOriginalConstructor()
->setMethods(['currentTime'])
->getMock();
$myClass
->method('currentTime')
->willReturn($currentTime);
$this->assertFalse($myClass->myFunction(time()));
}
答案 1 :(得分:0)
我们可以在命名空间级别覆盖time()
函数。查看https://www.schmengler-se.de/en/2011/03/php-mocking-built-in-functions-like-time-in-unit-tests/
但是,每次我们打电话给time()
时都会失败,这会导致嘲笑的时间:)
namespace MyClass;
function time()
{
return MyClassTest::$mockTime ?: \time();
}
class MyClassTest extends TestCase{
public static $mockTime;
public function test_my_function(){
self::$mockTime = '08:10';
$myClass = new MyClass();
//$myClass->currentTime() //will return 08:10
//do something with my function
}
答案 2 :(得分:0)
我知道我参加聚会有点晚了,但是如果您能够在您的环境中安装 php 扩展,您可以使用 https://github.com/slope-it/clock-mock,它可以透明地工作,对您的代码进行 0 次修改。此时,您可以删除 currentTime()
并仅使用 time()
。