Testing utilities for [thalo](https://docs.rs/thalo) apps.
# Examples
Create aggregate and events.
```
use thalo::{
aggregate::{Aggregate, TypeId},
event::EventType,
};
use thiserror::Error;
#[derive(Aggregate, Clone, Debug, Default, PartialEq, TypeId)]
struct BankAccount {
id: String,
opened: bool,
balance: f64,
}
#[derive(Clone, Debug, EventType)]
enum BankAccountEvent {
OpenedAccount { balance: f64 },
}
fn apply(bank_account: &mut BankAccount, event: BankAccountEvent) {
use BankAccountEvent::*;
match event {
OpenedAccount { balance } => {
bank_account.opened = true;
bank_account.balance = balance;
}
}
}
```
Test aggregate events.
```
# use thalo::{
# aggregate::{Aggregate, TypeId},
# event::EventType,
# };
# use thiserror::Error;
#
# #[derive(Aggregate, Clone, Debug, Default, PartialEq, TypeId)]
# struct BankAccount {
# id: String,
# opened: bool,
# balance: f64,
# }
#
# #[derive(Clone, Debug, EventType)]
# enum BankAccountEvent {
# OpenedAccount { balance: f64 },
# }
#
# fn apply(bank_account: &mut BankAccount, event: BankAccountEvent) {
# use BankAccountEvent::*;
#
# match event {
# OpenedAccount { balance } => {
# bank_account.opened = true;
# bank_account.balance = balance;
# }
# }
# }
#
#[cfg(test)]
mod tests {
use thalo_testing::*;
use super::{BankAccount, BankAccountEvent};
#[test]
fn opened_account() {
BankAccount::given(
"account-123",
BankAccountEvent::OpenedAccount {
balance: 0.0,
}
)
.should_eq(BankAccount {
id: "account-123".to_string(),
opened: true,
balance: 0.0,
});
}
}
```
Test aggregate commands.
```
# use thalo::{
# aggregate::{Aggregate, TypeId},
# event::EventType,
# };
# use thiserror::Error;
#
# #[derive(Aggregate, Clone, Debug, Default, PartialEq, TypeId)]
# struct BankAccount {
# id: String,
# opened: bool,
# balance: f64,
# }
#
# #[derive(Clone, Debug, EventType)]
# enum BankAccountEvent {
# OpenedAccount { balance: f64 },
# }
#
# fn apply(bank_account: &mut BankAccount, event: BankAccountEvent) {
# use BankAccountEvent::*;
#
# match event {
# OpenedAccount { balance } => {
# bank_account.opened = true;
# bank_account.balance = balance;
# }
# }
# }
#
impl BankAccount {
pub fn open_account(
&self,
initial_balance: f64,
) -> Result {
if self.opened {
return Err(BankAccountError::AlreadyOpened);
}
if initial_balance < 0.0 {
return Err(BankAccountError::NegativeAmount);
}
Ok(BankAccountEvent::OpenedAccount {
balance: initial_balance,
})
}
}
#[derive(Debug, Error)]
pub enum BankAccountError {
#[error("account already opened")]
AlreadyOpened,
#[error("negative amount")]
NegativeAmount,
}
#[cfg(test)]
mod tests {
use thalo_testing::*;
use super::{BankAccount, BankAccountError, BankAccountEvent};
#[test]
fn open_account() {
BankAccount::given_no_events("account-123")
.when(|bank_account| bank_account.open_account(0.0))
.then(Ok(BankAccountEvent::OpenedAccount {
balance: 0.0,
}));
}
#[test]
fn open_account_already_opened() {
BankAccount::given(
"account-123",
BankAccountEvent::OpenedAccount {
balance: 0.0,
},
)
.when(|bank_account| bank_account.open_account(50.0))
.then(Err(BankAccountError::AlreadyOpened));
}
#[test]
fn open_account_negative_amount() {
BankAccount::given_no_events()
.when(|bank_account| bank_account.open_account(-10.0))
.then(Err(BankAccountError::NegativeAmount));
}
```