作者:dengyuanc_928 | 来源:互联网 | 2023-05-18 19:33
MostoftheanswersIhaveseenonStackOverflowarewithoutusingtheDateTimeobject,andareinst
Most of the answers I have seen on StackOverflow are without using the DateTime
object, and are instead using the date()
function. This makes them very dirty solutions (overriding date()
, mocking a protected function of the subject under test, etc).
我在StackOverflow上看到的大多数答案都没有使用DateTime对象,而是使用了date()函数。这使得它们成为非常脏的解决方案(覆盖date(),模拟受测试对象的受保护功能等)。
Is there a way to mock DateTime
, effectively mocking the current date/time?
有没有办法模拟DateTime,有效地模拟当前日期/时间?
As an example, here is the code I'd like to test:
举个例子,这是我要测试的代码:
public function __construct(UserInterface $user, EntityManager $manager)
{
$this->user = $user;
$this->manager = $manager;
}
public function create(Tunnel $tunnel, $chain, $response)
{
$history = new CommandHistory();
$history->setTunnel($tunnel)
->setCommand($chain)
->setResponse($response)
->setUser($this->user)
;
$this->manager->persist($history);
$this->manager->flush();
}
Here is where I set the date and time in my CommandHistory
class:
这是我在CommandHistory类中设置日期和时间的地方:
class CommandHistory
{
// Property definitions...
public function __construct()
{
$this->time = new \DateTime();
}
}
And here is my unit test:
这是我的单元测试:
public function testCreate()
{
$user = new User();
$manager = $this->mockManagerWithUser($user);
$tunnel = $this->tunnel;
$chain = 'Commands`Chain';
$respOnse= 'This is the response!';
$creator = new CommandHistoryCreator($user, $manager);
$creator->create($tunnel, $chain, $response);
}
protected function mockManagerWithUser(UserInterface $user)
{
$manager = \Mockery::mock('Doctrine\ORM\EntityManager');
$manager->shouldReceive('persist')->once()->with(\Mockery::on(function(CommandHistory $argument) use ($user) {
return
$argument->getCommand() === 'Commands`Chain'
&& $argument->getResponse() === 'This is the response!'
&& $argument->getTunnel() === $this->tunnel
&& $argument->getUser() === $user
;
}));
$manager->shouldReceive('flush')->once()->withNoArgs();
return $manager;
}
As you can see, I've created a rather long-winded closure only to exclude the comparison of the field that contains the current time, and I feel like this is hurting the readability of my test.
正如你所看到的,我创建了一个相当冗长的闭包只是为了排除包含当前时间的字段的比较,我觉得这会损害我的测试的可读性。
Also, to preserve ease of use for people who are using this class, I don't want to have to make them pass in the current time to the create()
function. I believe adding strange behavior to my classes only to make them testable means I'm doing something wrong.
此外,为了保持使用此类的人的易用性,我不想让它们在当前时间传递给create()函数。我认为在我的类中添加奇怪的行为只是为了使它们可测试意味着我做错了。
1 个解决方案