问题描述
我来自 Python,您在 monkeypatch
中有 pytest
,所以我将我想做的操作称为monkeypatching,但是,我被告知实际操作更多地称为模拟一般。
无论如何,我的应用程序使用 ncurses
crate,我需要测试一些调用它的代码。我如何正确地修补(模拟)对 crate 的函数、方法和其他属性的调用?
例如
fn get_page(&self,commands: &[String]) -> Vec<String> {
match commands
.chunks(ncurses::LInes() as usize - 3)
.nth(self.page as usize - 1)
{
Some(cmds) => cmds.to_vec(),None => Vec::new(),}
}
解决方法
在 python 中,一切都是动态的和可修补的,但 rust 是编译的和具体的。因此,在您的源代码中,您必须明确地将工作代码和库代码分离。
trait NcursesImpl {
// all functions in ncurses that you want to use need to have implementations here.
/// Here is a default implementation that just delegates to ncurses
fn LINES(&self) -> c_int {
ncurses::LINES()
}
}
struct DefaultNCruses;
impl NCursesImpl for DefaultNCurses {
// no functions overridden,everything uses default implementations
}
struct LinesLiarNCurses {
lines: c_int,}
impl NCursesImpl for LinesLiarNCurses {
/// overrides default implementation for debug purposes
fn LINES(&self) -> c_int {
self.lines
}
}
get_page()
必须稍微改变以使用 NCursesImpl 而不是裸 ncurses。
fn get_page(&self,nc: &NCursesImpl,commands: &[String]) -> Vec<String> {
match commands
.chunks(nc.LINES() as usize - 3)
.nth(self.page as usize - 1)
{
Some(cmds) => cmds.to_vec(),None => Vec::new(),}
}
我不太确定 NCursesImpl 对象应该在哪里。在这里,我已将其设置为 get_page 调用的显式参数,但它实际上可能属于具有 Self
impl 的结构中的 get_page
成员。您可能希望将其存储在 Box<dyn NCursesImpl>
中,以便您的数据结构中不会有类型参数。