How can I test stdin and stdout?

前端 未结 1 1068
被撕碎了的回忆
被撕碎了的回忆 2020-11-27 07:24

I\'d like to write a prompt function that sends a passed-in string to stdout and then returns the string that it reads from stdin. How could I test it?

Here is an ex

相关标签:
1条回答
  • 2020-11-27 07:57

    Use dependency injection. Coupling it with generics and monomorphism, you don't lose any performance:

    use std::io::{self, BufRead, Write};
    
    fn prompt<R, W>(mut reader: R, mut writer: W, question: &str) -> String
    where
        R: BufRead,
        W: Write,
    {
        write!(&mut writer, "{}", question).expect("Unable to write");
        let mut s = String::new();
        reader.read_line(&mut s).expect("Unable to read");
        s
    }
    
    #[test]
    fn test_with_in_memory() {
        let input = b"I'm George";
        let mut output = Vec::new();
    
        let answer = prompt(&input[..], &mut output, "Who goes there?");
    
        let output = String::from_utf8(output).expect("Not UTF-8");
    
        assert_eq!("Who goes there?", output);
        assert_eq!("I'm George", answer);
    }
    
    fn main() {
        let stdio = io::stdin();
        let input = stdio.lock();
    
        let output = io::stdout();
    
        let answer = prompt(input, output, "Who goes there?");
        println!("was: {}", answer);
    }
    

    In many cases, you'd want to actually propagate the error back up to the caller instead of using expect, as IO is a very common place for failures to occur.


    This can be extended beyond functions into methods:

    use std::io::{self, BufRead, Write};
    
    struct Quizzer<R, W> {
        reader: R,
        writer: W,
    }
    
    impl<R, W> Quizzer<R, W>
    where
        R: BufRead,
        W: Write,
    {
        fn prompt(&mut self, question: &str) -> String {
            write!(&mut self.writer, "{}", question).expect("Unable to write");
            let mut s = String::new();
            self.reader.read_line(&mut s).expect("Unable to read");
            s
        }
    }
    
    #[test]
    fn test_with_in_memory() {
        let input = b"I'm George";
        let mut output = Vec::new();
    
        let answer = {
            let mut quizzer = Quizzer {
                reader: &input[..],
                writer: &mut output,
            };
    
            quizzer.prompt("Who goes there?")
        };
    
        let output = String::from_utf8(output).expect("Not UTF-8");
    
        assert_eq!("Who goes there?", output);
        assert_eq!("I'm George", answer);
    }
    
    fn main() {
        let stdio = io::stdin();
        let input = stdio.lock();
    
        let output = io::stdout();
    
        let mut quizzer = Quizzer {
            reader: input,
            writer: output,
        };
    
        let answer = quizzer.prompt("Who goes there?");
        println!("was: {}", answer);
    }
    
    0 讨论(0)
提交回复
热议问题