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
}
}