如何对 ncurses 板条箱进行猴子补丁模拟调用?

问题描述

我来自 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(),}
}

如何修补 ncurses::LInes() 调用

解决方法

在 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> 中,以便您的数据结构中不会有类型参数。