ranvier_runtime/
testkit.rs1use crate::Axon;
2use ranvier_core::{Bus, Outcome, transition::ResourceRequirement};
3use serde::{Serialize, de::DeserializeOwned};
4use std::any::Any;
5
6pub struct AxonTestKit<R> {
11 resources: R,
12 bus: Bus,
13}
14
15impl<R> AxonTestKit<R> {
16 pub fn new(resources: R) -> Self {
17 Self {
18 resources,
19 bus: Bus::new(),
20 }
21 }
22
23 pub fn with_bus(resources: R, bus: Bus) -> Self {
24 Self { resources, bus }
25 }
26
27 pub fn insert<T: Any + Send + Sync + 'static>(&mut self, value: T) -> &mut Self {
28 self.bus.insert(value);
29 self
30 }
31
32 pub fn bus(&self) -> &Bus {
33 &self.bus
34 }
35
36 pub fn bus_mut(&mut self) -> &mut Bus {
37 &mut self.bus
38 }
39
40 pub fn resources(&self) -> &R {
41 &self.resources
42 }
43
44 pub fn resources_mut(&mut self) -> &mut R {
45 &mut self.resources
46 }
47
48 pub fn into_parts(self) -> (R, Bus) {
49 (self.resources, self.bus)
50 }
51}
52
53impl<R> AxonTestKit<R>
54where
55 R: ResourceRequirement,
56{
57 pub async fn run<In, Out, E>(
58 &mut self,
59 axon: &Axon<In, Out, E, R>,
60 input: In,
61 ) -> Outcome<Out, E>
62 where
63 In: Send + Sync + Serialize + DeserializeOwned + 'static,
64 Out: Send + Sync + Serialize + DeserializeOwned + 'static,
65 E: Send + Sync + Serialize + DeserializeOwned + std::fmt::Debug + 'static,
66 {
67 axon.execute(input, &self.resources, &mut self.bus).await
68 }
69}
70
71#[cfg(test)]
72mod tests {
73 use super::*;
74 use ranvier_core::{Outcome, Transition};
75 use serde::{Deserialize, Serialize};
76
77 #[derive(Debug, Clone, Serialize, Deserialize)]
78 pub enum TestInfallible {}
79
80 #[derive(Clone)]
81 struct MockResources {
82 offset: usize,
83 }
84
85 impl ranvier_core::transition::ResourceRequirement for MockResources {}
86
87 #[derive(Clone)]
88 struct SumWithBus;
89
90 #[async_trait::async_trait]
91 impl Transition<usize, usize> for SumWithBus {
92 type Error = TestInfallible;
93 type Resources = MockResources;
94
95 async fn run(
96 &self,
97 state: usize,
98 resources: &Self::Resources,
99 bus: &mut Bus,
100 ) -> Outcome<usize, Self::Error> {
101 let bus_value = bus.read::<usize>().copied().unwrap_or_default();
102 Outcome::next(state + resources.offset + bus_value)
103 }
104 }
105
106 #[tokio::test]
107 async fn testkit_executes_with_mocked_resources_and_bus_values() {
108 let axon = Axon::<usize, usize, TestInfallible, MockResources>::new("Sum").then(SumWithBus);
109 let mut kit = AxonTestKit::new(MockResources { offset: 7 });
110 kit.insert(5usize);
111
112 let result = kit.run(&axon, 10).await;
113 match result {
114 Outcome::Next(value) => assert_eq!(value, 22),
115 _ => panic!("expected Outcome::Next"),
116 }
117 }
118}