Testing

测试并发系统比单线程应用程序更困难,因为测试本身和应用程序在不同的线程上运行。 此外,由于Riker的弹性自我修复方法,恐慌被隔离,处理和故障组件重新启动,检测测试失败证明是具有挑战性的。

为了帮助简化测试,riker-testkit引入了一个“探测器”,可以通过消息传递或作为 Actor道具的一部分发送给 Actor。 然后,探针可以将值发送回测试线程。

以下是测试actor重启的示例:

  1. #[macro_use]
  2. extern crate riker_testkit;
  3. type TestProbe = ChannelProbe<(), ()>;
  4. #[derive(Clone, Debug)]
  5. enum TestMsg {
  6. Probe(TestProbe),
  7. Panic,
  8. }
  9. impl Into<ActorMsg<TestMsg>> for TestMsg {
  10. fn into(self) -> ActorMsg<TestMsg> {
  11. ActorMsg::User(self)
  12. }
  13. }
  14. struct MyActor;
  15. impl MyActor {
  16. fn new() -> BoxActor<TestMsg> {
  17. Box::new(MyActor)
  18. }
  19. }
  20. impl Actor for MyActor {
  21. type Msg = TestMsg;
  22. fn receive(&mut self,
  23. _ctx: &Context<Self::Msg>,
  24. msg: Self::Msg,
  25. _sender: Option<ActorRef<Self::Msg>>)
  26. {
  27. match msg {
  28. TestMsg::Panic => {
  29. // panic the actor to simulate failure
  30. panic!("// TEST PANIC // TEST PANIC // TEST PANIC //");
  31. }
  32. TestMsg::Probe(probe) => {
  33. // received probe
  34. // let's emit () empty tuple back to listener
  35. probe.event(());
  36. }
  37. };
  38. }
  39. }
  40. #[test]
  41. fn panic_actor() {
  42. let model: DefaultModel<TestMsg> = DefaultModel::new();
  43. let sys = ActorSystem::new(&model).unwrap();
  44. let props = Props::new(Box::new(MyActor::new));
  45. let actor = sys.actor_of(props, "my-actor").unwrap();
  46. // Make the test actor panic
  47. actor.tell(TestMsg::Panic, None);
  48. // Prepare a probe
  49. let (probe, listen) = probe::<()>();
  50. // Send the probe to the panicked actor
  51. // which would have been restarted
  52. actor.tell(TestMsg::Probe(probe), None);
  53. // Testkit provides a macro to assert the result
  54. // that gets emmitted from the probe to the listener.
  55. // Here we're expecting () empty tuple.
  56. p_assert_eq!(listen, ());
  57. }

此测试显示我们的actor在失败后成功重启。 它能够继续接收消息,在这种情况下是探测。 宏p_assert_eq! 等待(块)侦听器,直到从探测器接收到值。