问题描述
我目前正在构建一个高度依赖文件IO的应用程序,因此很明显,我的代码很多部分都有File::open(file)
。
做一些集成测试是可以的,我可以轻松设置文件夹以加载文件和所需的方案。
问题出在我要进行单元测试和代码分支的任何地方。我知道那里有很多声称可以进行模拟的模拟库,但是我觉得我最大的问题是代码设计本身。
例如,我将使用任何面向对象的语言(在示例中为java)执行相同的代码,我可以编写一些接口,并在测试中简单地覆盖我要模拟的默认行为,设置一个假{ {1}},无论是通过固定收益重新实现,还是使用诸如嘲笑之类的模拟框架。
ClientRepository
但是由于我们最终将数据与行为混合在一起,所以我无法在生锈中得到相同的结果。
在RefCell documentation上,有一个与我在java上给出的示例类似的示例。一些答案指向特征clojures,conditional compiliation
我们可能会测试一些场景,首先是一些mod.rs中的公共功能
public interface ClientRepository {
Client getClient(int id)
}
public class ClientRepositoryDB {
private ClientRepository repository;
//getters and setters
public Client getClientById(int id) {
Client client = repository.getClient(id);
//Some data manipulation and validation
}
}
第二个相同的函数变成一个特征,并通过某些struct实现它。
#[derive(Serialize,Deserialize,Debug,Clone)]
pub struct SomeData {
pub name: Option<String>,pub address: Option<String>,}
pub fn get_some_data(file_path: PathBuf) -> Option<SomeData> {
let mut contents = String::new();
match File::open(file_path) {
Ok(mut file) => {
match file.read_to_string(&mut contents) {
Ok(result) => result,Err(_err) => panic!(
panic!("Problem reading file")
),};
}
Err(err) => panic!("File not find"),}
// using serde for operate on data output
let some_data: SomeData = match serde_json::from_str(&contents) {
Ok(some_data) => some_data,Err(err) => panic!(
"An error occour when parsing: {:?}",err
),};
//we might do some checks or whatever here
Some(some_data) or None
}
mod test {
use super::*;
#[test]
fn test_if_scenario_a_happen() -> std::io::Result<()> {
//tied with File::open
let some_data = get_some_data(PathBuf::new);
assert!(result.is_some());
Ok(())
}
#[test]
fn test_if_scenario_b_happen() -> std::io::Result<()> {
//We might need to write two files,and we want to test is the logic,not the file loading itself
let some_data = get_some_data(PathBuf::new);
assert!(result.is_none());
Ok(())
}
}
在两个示例中,由于要绑定
#[derive(Serialize,Clone)]
pub struct SomeData {
pub name: Option<String>,}
trait GetSomeData {
fn get_some_data(&self,file_path: PathBuf) -> Option<SomeData>;
}
pub struct SomeDataService {}
impl GetSomeData for SomeDataService {
fn get_some_data(&self,file_path: PathBuf) -> Option<SomeData> {
let mut contents = String::new();
match File::open(file_path) {
Ok(mut file) => {
match file.read_to_string(&mut contents) {
Ok(result) => result,Err(_err) => panic!("Problem reading file"),};
}
Err(err) => panic!("File not find"),}
// using serde for operate on data output
let some_data: SomeData = match serde_json::from_str(&contents) {
Ok(some_data) => some_data,Err(err) => panic!("An error occour when parsing: {:?}",err),};
//we might do some checks or whatever here
Some(some_data) or None
}
}
impl SomeDataService {
pub fn do_something_with_data(&self) -> Option<SomeData> {
self.get_some_data(PathBuf::new())
}
}
mod test {
use super::*;
#[test]
fn test_if_scenario_a_happen() -> std::io::Result<()> {
//tied with File::open
let service = SomeDataService{}
let some_data = service.do_something_with_data(PathBuf::new);
assert!(result.is_some());
Ok(())
}
}
,因此我们很难对其进行测试,并且可以肯定的是,这可能会扩展到任何不确定性函数,例如时间,数据库连接等。
您将如何设计此代码或任何类似的代码,以简化单元测试和更好的设计?
很抱歉,很长的帖子。
~~马铃薯图像~~
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)