Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improving the tests #25

Merged
merged 1 commit into from
Mar 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
275 changes: 110 additions & 165 deletions tests/aggregate_combined_test.rs

Large diffs are not rendered by default.

63 changes: 21 additions & 42 deletions tests/aggregate_test.rs
Original file line number Diff line number Diff line change
@@ -1,33 +1,20 @@
use std::collections::HashMap;
use std::error::Error;
use std::sync::{Arc, Mutex};
use std::thread;

use derive_more::Display;

use fmodel_rust::aggregate::{
EventRepository, EventSourcedAggregate, StateRepository, StateStoredAggregate,
};
use fmodel_rust::decider::Decider;

use crate::api::{
CancelOrderCommand, CreateOrderCommand, OrderCancelledEvent, OrderCommand, OrderCreatedEvent,
OrderEvent, OrderUpdatedEvent, UpdateOrderCommand,
OrderEvent, OrderState, OrderUpdatedEvent, UpdateOrderCommand,
};
use crate::application::AggregateError;

mod api;

/// Error type for the application/aggregate
#[derive(Debug, Display)]
#[allow(dead_code)]
enum AggregateError {
FetchEvents(String),
SaveEvents(String),
FetchState(String),
SaveState(String),
}

impl Error for AggregateError {}
mod application;

/// A simple in-memory event repository - infrastructure
struct InMemoryOrderEventRepository {
Expand Down Expand Up @@ -119,39 +106,31 @@ impl StateRepository<OrderCommand, OrderState, i32, AggregateError>
}
}

#[derive(Debug, Clone, PartialEq)]
struct OrderState {
order_id: u32,
customer_name: String,
items: Vec<String>,
is_cancelled: bool,
}

/// Decider for the Order aggregate - Domain logic
fn decider<'a>() -> Decider<'a, OrderCommand, OrderState, OrderEvent> {
Decider {
decide: Box::new(|command, state| match command {
OrderCommand::Create(create_cmd) => {
OrderCommand::Create(cmd) => {
vec![OrderEvent::Created(OrderCreatedEvent {
order_id: create_cmd.order_id,
customer_name: create_cmd.customer_name.to_owned(),
items: create_cmd.items.to_owned(),
order_id: cmd.order_id,
customer_name: cmd.customer_name.to_owned(),
items: cmd.items.to_owned(),
})]
}
OrderCommand::Update(update_cmd) => {
if state.order_id == update_cmd.order_id {
OrderCommand::Update(cmd) => {
if state.order_id == cmd.order_id {
vec![OrderEvent::Updated(OrderUpdatedEvent {
order_id: update_cmd.order_id,
updated_items: update_cmd.new_items.to_owned(),
order_id: cmd.order_id,
updated_items: cmd.new_items.to_owned(),
})]
} else {
vec![]
}
}
OrderCommand::Cancel(cancel_cmd) => {
if state.order_id == cancel_cmd.order_id {
OrderCommand::Cancel(cmd) => {
if state.order_id == cmd.order_id {
vec![OrderEvent::Cancelled(OrderCancelledEvent {
order_id: cancel_cmd.order_id,
order_id: cmd.order_id,
})]
} else {
vec![]
Expand All @@ -161,13 +140,13 @@ fn decider<'a>() -> Decider<'a, OrderCommand, OrderState, OrderEvent> {
evolve: Box::new(|state, event| {
let mut new_state = state.clone();
match event {
OrderEvent::Created(created_event) => {
new_state.order_id = created_event.order_id;
new_state.customer_name = created_event.customer_name.to_owned();
new_state.items = created_event.items.to_owned();
OrderEvent::Created(evt) => {
new_state.order_id = evt.order_id;
new_state.customer_name = evt.customer_name.to_owned();
new_state.items = evt.items.to_owned();
}
OrderEvent::Updated(updated_event) => {
new_state.items = updated_event.updated_items.to_owned();
OrderEvent::Updated(evt) => {
new_state.items = evt.updated_items.to_owned();
}
OrderEvent::Cancelled(_) => {
new_state.is_cancelled = true;
Expand All @@ -192,7 +171,7 @@ async fn es_test() {
// This creates another pointer to the same allocation, increasing the strong reference count.
let aggregate2 = Arc::clone(&aggregate);

// Lets spawn two threads to simulate two concurrent requests
// Let's spawn two threads to simulate two concurrent requests
let handle1 = thread::spawn(|| async move {
let command = OrderCommand::Create(CreateOrderCommand {
order_id: 1,
Expand Down
87 changes: 69 additions & 18 deletions tests/api.rs → tests/api/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,26 @@
// Order API
// ###################################################################
// ############################ Order API ############################
// ###################################################################

/// The state of the Order entity
#[derive(Debug, Clone, PartialEq)]
pub struct OrderState {
pub order_id: u32,
pub customer_name: String,
pub items: Vec<String>,
pub is_cancelled: bool,
}

/// The state of the ViewOrder entity / It represents the Query Model
#[derive(Debug, Clone, PartialEq)]
pub struct OrderViewState {
pub order_id: u32,
pub customer_name: String,
pub items: Vec<String>,
pub is_cancelled: bool,
}

/// All variants of Order commands
#[derive(Debug, Clone, PartialEq)]
#[allow(dead_code)]
pub enum OrderCommand {
Expand All @@ -25,6 +47,7 @@ pub struct CancelOrderCommand {
pub order_id: u32,
}

/// Provides a way to get the id of the Order commands
impl OrderCommand {
#[allow(dead_code)]
pub fn id(&self) -> u32 {
Expand All @@ -36,15 +59,7 @@ impl OrderCommand {
}
}

impl ShipmentCommand {
#[allow(dead_code)]
pub fn id(&self) -> u32 {
match self {
ShipmentCommand::Create(c) => c.shipment_id.to_owned(),
}
}
}

/// All variants of Order events
#[derive(Debug, Clone, PartialEq)]
#[allow(dead_code)]
pub enum OrderEvent {
Expand All @@ -71,6 +86,7 @@ pub struct OrderCancelledEvent {
pub order_id: u32,
}

/// Provides a way to get the id of the Order events
impl OrderEvent {
#[allow(dead_code)]
pub fn id(&self) -> u32 {
Expand All @@ -81,16 +97,30 @@ impl OrderEvent {
}
}
}
impl ShipmentEvent {
#[allow(dead_code)]
pub fn id(&self) -> u32 {
match self {
ShipmentEvent::Created(c) => c.shipment_id.to_owned(),
}
}

// ######################################################################
// ############################ Shipment API ############################
// ######################################################################

/// The state of the Shipment entity
#[derive(Debug, Clone, PartialEq)]
pub struct ShipmentState {
pub shipment_id: u32,
pub order_id: u32,
pub customer_name: String,
pub items: Vec<String>,
}

// Shipment API
/// The state of the ViewShipment entity / It represents the Query Model
#[derive(Debug, Clone, PartialEq)]
pub struct ShipmentViewState {
pub shipment_id: u32,
pub order_id: u32,
pub customer_name: String,
pub items: Vec<String>,
}

/// All variants of Shipment commands
#[derive(Debug, PartialEq, Clone)]
#[allow(dead_code)]
pub enum ShipmentCommand {
Expand All @@ -105,6 +135,17 @@ pub struct CreateShipmentCommand {
pub items: Vec<String>,
}

/// Provides a way to get the id of the Shipment commands
impl ShipmentCommand {
#[allow(dead_code)]
pub fn id(&self) -> u32 {
match self {
ShipmentCommand::Create(c) => c.shipment_id.to_owned(),
}
}
}

/// All variants of Shipment events
#[derive(Debug, PartialEq, Clone)]
#[allow(dead_code)]
pub enum ShipmentEvent {
Expand All @@ -117,3 +158,13 @@ pub struct ShipmentCreatedEvent {
pub customer_name: String,
pub items: Vec<String>,
}

/// Provides a way to get the id of the Shipment events
impl ShipmentEvent {
#[allow(dead_code)]
pub fn id(&self) -> u32 {
match self {
ShipmentEvent::Created(c) => c.shipment_id.to_owned(),
}
}
}
Loading