testing - 如何在不要求参数函数可变的情况下测试元函数?
问题描述
我编写了一个save
以函数为参数的函数:
fn save(method:&dyn Fn(&'static str)) {
method("Hello world");
}
fn print(string:&'static str) {
println!("{}", string);
}
fn main() {
save(&print)
}
这很好用!但我现在想测试save
。我认为这样做的最好方法是使用FnMut
:
fn save(method: &mut dyn FnMut(&'static str)) {
method("Hello world");
}
fn print(string: &'static str) {
println!("{}", string);
}
fn main() {
save(&mut print)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn save_test() {
let actual = {
let mut actual = String::new();
let mut method = |string: &'static str| {
actual = format!("{}{}", actual, string);
};
save(&mut method);
save(&mut method);
actual
};
let expected = "Hello worldHello world".to_string();
assert_eq!(actual, expected);
}
}
这仍然有效并完成了我想要的一切!但是现在我每次call
保存时都必须使用可变引用。虽然这不会影响功能,但它会混淆代码。有没有更好的方法来实现相同的结果?
解决方案
您可以使用RefCell
来获得内部可变性,允许您通过共享引用来可变变量。它非常适合测试这样的事情:
#[cfg(test)]
mod tests {
use std::cell::RefCell;
use super::*;
#[test]
fn save_test() {
let actual = {
// wrap "actual" in a RefCell, which allows for interior mutability
let actual = RefCell::new(String::new());
let method = |string: &'static str| {
// mutably borrow the string at runtime
// (can panic in already borrowed, but not a problem here)
let mut actual = actual.borrow_mut();
// append string (equivalent to your format!() but can be more
// efficient)
actual.push_str(string);
};
save(&method);
save(&method);
// move string out of RefCell
actual.into_inner()
};
let expected = "Hello worldHello world".to_string();
assert_eq!(actual, expected);
}
}
推荐阅读
- javascript - 选择第一个下拉菜单并在第二个下拉菜单上显示相同的选定选项值
- joomla3.0 - 谷歌搜索控制台两个问题移动技术可点击元素靠得太近和内容比屏幕宽
- cypress - Cypress cy.visit 导致 401 未授权
- php - 并非所有键都散列到标记键的同一插槽,如何解决此问题
- django - Django Rest Framework 中的 NameError,它显示我的模型名称未定义
- javascript - 获取表格单元格数据
- performance - 有没有办法找出或控制 Elixir 中哪个 CPU 内核上运行的进程?
- google-cloud-platform - 当自定义日志消息传送到 GCP Stackdriver 时发送通知
- javascript - 如何通过表单提交保持 Chrome 扩展在页面重新加载时运行?
- r - 闪亮的 fileInput() 对多个文件选择没有反应