cloned_writer.clone().write_all(b"Even more stuff\n").unwrap();
}
writer.write_all(b".\n").unwrap();
assert_eq!(into_string(writer),"Some stuff\nOther stuff\nEven more stuff\n.\n");
}
Ако сте започнали домашно 3, може да си задавате въпроса "а как да тествам, че logger-а пише във файл?" Отговора е: чрез нещо друго, което имплементира Write.
Бихте могли да подадете Vec<u8>, например, но как ще го извадите после, за да проверите какво е било записано в него? Всичко, което приема Write структура, ще иска да я консумира, или поне да вземе mutable reference, а това се усложнява, когато искате да тествате logger-и, които споделят един такъв writer.
Очакваме да напишете TestWriter, който да е Write, и да може да се клонира със споделяне на вътрешния буфер. Дефиницията би изглеждала нещо такова:
use std::io::Write;
pub struct TestWriter {
/// Каквито полета ви трябват, но вероятно нещо, което обвива Vec<u8>
}
impl TestWriter {
/// Конструира нов TestWriter с празен контейнер за байтове.
///
pub fn new() -> Self {
unimplemented!()
}
/// Консумира структурата и връща Vec с байтове, в който се съдържа каквото е било писано
/// чрез методите на `Write` trait-а.
///
pub fn into_inner(self) -> Vec<u8> {
unimplemented!()
}
/// Този метод съществува по-скоро за демонстрация как бихте могли удобно да използвате този
/// тип, без да жонглирате байтове. Няма да се тества, ако решите да го махнете или пренапишете
/// някак.
///
pub fn into_string(self) -> String {
String::from_utf8(self.into_inner()).unwrap()
}
}
impl Write for TestWriter {
/// Подходяща имплементация на Write
}
impl Clone for TestWriter {
/// Подходяща имплементация на Clone
}
Употребата в един примерен тест за нещо, което има нужда от writer, би могла да изглежда така:
let out = TestWriter::new();
{
let thing = ThingThatWeAreTesting::new(out.clone());
thing.wake_up_neo();
thing.the_matrix_has_you();
thing.follow_the_white_rabbit();
}
assert_eq!(out.into_string(), "Knock, knock, Neo");