Random Rust:模拟具有gen_范围的rand函数

Random Rust:模拟具有gen_范围的rand函数,random,rust,mocking,Random,Rust,Mocking,我正在编写一个小程序,从枚举中随机选择一个条目。示例代码: #[derive(Debug)] enum SettlementSize { VILLAGE, TOWN, CITY } impl Distribution<SettlementSize> for Standard { fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> SettlementSize {

我正在编写一个小程序,从枚举中随机选择一个条目。示例代码:

#[derive(Debug)]
enum SettlementSize {
    VILLAGE,
    TOWN,
    CITY
}

impl Distribution<SettlementSize> for Standard {
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> SettlementSize {
        let res = rng.gen_range(0, 3);
        match res {
            0 => SettlementSize::VILLAGE,
            1 => SettlementSize::TOWN,
            2 => SettlementSize::CITY,
            _ => panic!("Unknown value!")
        }
    }
}

fn get_settlement_size(mut rng: impl RngCore) -> SettlementSize {
    let size: SettlementSize = rng.gen();
    size
}
不幸的是,这不起作用。当我添加一些println时,返回的值来自:

rng.gen_range(0, 3);
始终为0。我将StepRng代码复制到我的测试模块中,以便在其中添加println,我看到调用了next_u32和next_u64。然而,后来代码消失在
UniformSampler
中,在这一点上,我很难理解。我做错了什么?我能以某种方式保留可测试性吗(这意味着我能在脑海中为随机设置固定结果)?

你说得对, 很容易模拟RngCore特征的原始功能, 但它们用于避免低阶位和 模量计算的偏差使得模拟模型变得非常棘手 RngCore中更复杂的函数

在我看来,实现这一点最简单的方法是在使用Rng和要测试的代码之间放置一层

因此,与此相反:

fn get_settlement_size(mut rng: impl RngCore) -> SettlementSize {
    let size: SettlementSize = rng.gen();
    size
}
你有

trait RngWrapper {
    fn get_settlement_size(&mut self) -> SettlementSize;
}

fn get_settlement_size(rng: &mut impl RngWrapper) -> SettlementSize {
    rng.get_settlement_size()
}
现在,您的“真正”实现如下所示

impl Distribution<SettlementSize> for Standard {
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> SettlementSize {
        let res = rng.gen_range(0..3);
        match res {
            0 => SettlementSize::VILLAGE,
            1 => SettlementSize::TOWN,
            2 => SettlementSize::CITY,
            _ => panic!("Unknown value!"),
        }
    }
}

struct Random<'a, R: RngCore> {
    rng: &'a mut R,
}

impl<'a, R> RngWrapper for Random<'a, R>
where
    R: RngCore,
{
    fn get_settlement_size(&mut self) -> SettlementSize {
        self.rng.gen()
    }
}
现在,您可以测试任何使用
get\u consolution\u size()
的东西,但您还没有解决
随机测试的问题
impl Distribution<SettlementSize> for Standard {
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> SettlementSize {
        let res = rng.gen_range(0..3);
        match res {
            0 => SettlementSize::VILLAGE,
            1 => SettlementSize::TOWN,
            2 => SettlementSize::CITY,
            _ => panic!("Unknown value!"),
        }
    }
}

struct Random<'a, R: RngCore> {
    rng: &'a mut R,
}

impl<'a, R> RngWrapper for Random<'a, R>
where
    R: RngCore,
{
    fn get_settlement_size(&mut self) -> SettlementSize {
        self.rng.gen()
    }
}
struct AlwaysTown {}

impl RngWrapper for AlwaysTown {
    fn get_settlement_size(&mut self) -> SettlementSize {
        SettlementSize::TOWN
    }
}