Skip to content

Commit

Permalink
Add DiceGenMock for mocking the dice in unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
carsten-wenderdel committed Aug 12, 2023
1 parent f4ed0c1 commit 43a178a
Showing 1 changed file with 86 additions and 16 deletions.
102 changes: 86 additions & 16 deletions src/dice_gen.rs
Original file line number Diff line number Diff line change
@@ -1,40 +1,80 @@
pub struct DiceGen {
pub(crate) trait DiceGen {
/// Returns two random dice with values each between 1 and 6. Not sorted by size.
fn roll(&mut self) -> (usize, usize);
}

pub(crate) struct FastrandDice {
generator: fastrand::Rng,
}

impl DiceGen {
impl DiceGen for FastrandDice {
/// Returns two random dice with values each between 1 and 6. Not sorted by size.
fn roll(&mut self) -> (usize, usize) {
let random = self.generator.usize(0..36);
let die1 = random / 6 + 1;
let die2 = random % 6 + 1;
(die1, die2)
}
}

impl FastrandDice {
#[allow(dead_code)]
pub fn new() -> DiceGen {
DiceGen {
pub fn new() -> FastrandDice {
FastrandDice {
generator: fastrand::Rng::new(),
}
}

#[allow(dead_code)]
pub fn with_seed(seed: u64) -> DiceGen {
DiceGen {
pub(crate) fn with_seed(seed: u64) -> FastrandDice {
FastrandDice {
generator: fastrand::Rng::with_seed(seed),
}
}
}

/// Returns two random dice with values each between 1 and 6. Not sorted by size.
#[allow(dead_code)]
pub fn roll(&mut self) -> (usize, usize) {
let random = self.generator.usize(0..36);
let die1 = random / 6 + 1;
let die2 = random % 6 + 1;
(die1, die2)
#[cfg(test)]
/// Use this for unit tests where you want to control the dice.
pub(crate) struct DiceGenMock {
dice: Vec<(usize, usize)>,
no_calls: usize, // how often `roll` has been called.
}

#[cfg(test)]
impl DiceGen for DiceGenMock {
fn roll(&mut self) -> (usize, usize) {
let dice = self.dice[self.no_calls];
self.no_calls += 1;
dice
}
}

#[cfg(test)]
impl DiceGenMock {
pub(crate) fn new(dice: &[(usize, usize)]) -> DiceGenMock {
DiceGenMock {
dice: dice.to_vec(),
no_calls: 0,
}
}

pub(crate) fn assert_all_dice_were_used(&self) {
assert_eq!(
self.dice.len(),
self.no_calls,
"Not all dice of the mock have been used"
);
}
}

#[cfg(test)]
mod tests {
use crate::dice_gen::DiceGen;
mod fastrand_dice_tests {
use crate::dice_gen::{DiceGen, FastrandDice};

#[test]
fn all_numbers_are_occurring() {
// Given
let mut gen = DiceGen::with_seed(123);
let mut gen = FastrandDice::with_seed(123);
let mut count1 = [0, 0, 0, 0, 0, 0];
let mut count2 = count1;
// When
Expand All @@ -52,3 +92,33 @@ mod tests {
}
}
}

#[cfg(test)]
mod dice_gen_mock_tests {
use crate::dice_gen::{DiceGen, DiceGenMock};

#[test]
// #[should_panic]
fn roll_returns_given_dice() {
let mut dice_gen = DiceGenMock::new(&[(3, 2), (1, 6)]);
assert_eq!(dice_gen.roll(), (3, 2));
assert_eq!(dice_gen.roll(), (1, 6));
}

#[test]
// #[should_panic]
#[should_panic(expected = "Not all dice of the mock have been used")]
fn assert_all_dice_were_used() {
let mut dice_gen = DiceGenMock::new(&[(3, 2), (1, 6)]);
dice_gen.roll();
dice_gen.assert_all_dice_were_used();
}

#[test]
#[should_panic(expected = "index out of bounds: the len is 1 but the index is 1")]
fn panics_when_roll_is_called_too_often() {
let mut dice_gen = DiceGenMock::new(&[(3, 2)]);
dice_gen.roll();
dice_gen.roll();
}
}

0 comments on commit 43a178a

Please sign in to comment.