构建没有
直接结果的代码测试的方法是什么?
假设我们有一个非常简单(但相当粗鲁)的过程:
- 用户注册网站
- 两天通票
- 发送提醒电子邮件
- 更新某些数据库字段
- 十天通行证
- 发送"c'ya"电子邮件
- 删除帐户
我可以为每组子任务编写测试(发送电子邮件,更新数据库等)。但是,我如何编写结构良好的测试,其内容如下:
"注册两天后,应发送提醒电子邮件"注册十天后,帐户将被删除"
虽然我使用的是PHP和PHPUnit,但我觉得这个问题可能/可能不是语言不可知的。
基于事件机制的实现。例如,当代码中某处的事件侦听器收到带有用户 id 的事件user:reminder
时,您只需要:
1) 通过手动发送该事件来测试提醒发送脚本:
$eventBus->init();
$eventBus->attachListener($reminderListener);
$eventBus->fire(new ReminderEvent($user->id));
$this->expect(...); // reminder must be `sent`
2) 测试在时间流逝时生成事件:
$time = now();
$delay = ...;
$emitter = new RemindEventEmitter($user->id, $time + $delay)
$eventBus->addEmitter($emitter);
$eventBus->setCurrentTime($time); // when we just registered emitter...
$eventBus->run();
$this->expectNot(...); // ... that event _must not_ be fired
$eventBus->setCurrentTime($time + $delay); // manually skip $delay time ...
$eventBus->run();
$this->expect(...); // test that event _must_ be fired
并且事件生成/调度的事情(在我的示例中$eventBus
)必须在可模拟/可替换的时间获取器上中继:
// in production code
$eventBus->setCurrentTime(now());
// elsewhere in tests
$eventBus->setCurrentTime(<point in time you want to test against>);