ruabmbua / hidapi-rs

Rust bindings for the hidapi C library
MIT License
172 stars 81 forks source link

Thoughts on separate out HidDevice traits publish for mocking read/writes? #47

Closed jacobrosenthal closed 4 years ago

jacobrosenthal commented 4 years ago

Does anyone have a good mocking/testing strategy around HidDevice.read/write?

It seems like one solution is separating the HidDevice traits so I can make a fake one myself and pass into my function by trait instead of concrete.

Thoughts?

ruabmbua commented 4 years ago

You can always define your own trait, and implement it for the real HidDevice, and for your mock version.

Example:

use hidapi::HidDevice;

trait HidMockable {
    fn my_write(&self, data: &[u8]) -> HidResult<usize>;
    fn my_read(&self, buf: &mut [u8]) -> HidResult<usize>;
    // etc...
}

impl HidMockable for HidDevice {
    fn my_write(&self, data: &[u8]) -> HidResult<usize> {
        self.write(data)
    }
    fn my_read(&self, buf: &mut [u8]) -> HidResult<usize> {
        self.read(buf)
    }
    // etc...
}

struct MyMock;

impl HidMockable for MyMock { ... }
ruabmbua commented 4 years ago

You would then use the HidMockable trait to pass around your exchangeable implementation.

fn takes_hidmockable<T: HidMockable>(mock_or_real: &T) {
   // Do stuff with device
}
jacobrosenthal commented 4 years ago

Thanks! that worked great. I was so close :) If future folks want to see what I came up with https://github.com/jacobrosenthal/uf2-rs/blob/e9b633f7e7e83d1730a50987ef041b81e9741da5/src/lib.rs#L701 https://github.com/jacobrosenthal/uf2-rs/blob/e9b633f7e7e83d1730a50987ef041b81e9741da5/src/lib.rs#L701 Still a lot of boilerplate in the closures, but got my tests to pass and code to work :)

Thanks again