Reputation: 71989
I have a function that takes an input stream, processes its data, and then returns something, basically a more complicated version of this:
fn read_number_from_stream(input: &mut io::BufRead) -> io::Result<u32> {
// code that does something useful here
Ok(0)
}
Now I want to write a test for this function.
#[test]
fn input_with_zero_returns_zero() {
let test_input = read_from_string("0\n");
assert_eq!(Ok(0), read_number_from_stream(test_input));
}
How do I implement read_from_string
? Older versions of Rust apparently provided std::io::mem::MemReader
, but the entire std::io::mem
module seems to be gone in more recent versions of Rust (I'm using the unstable 1.5 branch).
Upvotes: 17
Views: 9288
Reputation: 65782
The documentation for each trait lists the available implementations. Here's the documentation page for BufRead
. We can see that &'a [u8]
(a slice of bytes) implements BufRead
. We can obtain a slice of bytes from a string and pass a mutable reference to that slice to read_number_from_stream
:
use std::io;
fn read_number_from_stream(input: &mut impl io::BufRead) -> io::Result<u32> {
// code that does something useful here
Ok(0)
}
fn read_from_string(s: &str) -> &[u8] {
s.as_bytes()
}
fn main() {
let mut test_input = read_from_string("0\n");
read_number_from_stream(&mut test_input);
}
If the buffer is not expected to contain UTF-8, or you just care about a particular ASCII-compatible subset of characters, you may want to define the test input as a byte string, rather than as a normal string. A byte string is written like a normal string, prefixed with b
, e.g. b"0\n"
. The type of a byte string is &[u8; N]
, where N
is the length of the string. Since that type doesn't implement BufRead
, we need to cast it to &[u8]
.
fn main() {
let mut test_input = b"0\n" as &[u8];
read_number_from_stream(&mut test_input);
}
Upvotes: 21