<!-- Source: https://medius.k4tech.net/library/guides/testing -->
# Testing without hardware

_Assert the frames with MockBox_

With the [`mock`](/library/features/mock.md) feature, drive a [`Device`](/library/connection.md) with a [`MockBox`](/library/features/mock.md) and assert the queued frames through [`recorded_frames`](/library/features/mock.md#inspect).

```bash
cargo add medius --features mock
```

#### EXAMPLE

```rust
use medius::{Button, Device, FrameType, MockBox};

#[test]
fn press_queues_an_inject() {
    let mock = MockBox::new();
    let device = Device::with_mock(mock.clone());

    device.press(Button::Left).unwrap();

    assert!(mock.saw(FrameType::Inject));
    let frame = mock
        .recorded_frames()
        .into_iter()
        .find(|f| f.ty == FrameType::Inject)
        .unwrap();
    assert_eq!(frame.payload, vec![0, 0, 0, 1]);
}
```

## Driving logs in a test

_Push log lines with a MockBox_

`push_log` on a `MockBox` emits a [`LOG`](/native/commands/admin.md#log) frame that surfaces on [`logs()`](/library/diagnostics.md#logs) like a real one.

#### EXAMPLE

```rust
use medius::{Device, LogLevel, MockBox};
use std::time::Duration;

#[test]
fn logs_reach_the_stream() {
    let mock = MockBox::new();
    let device = Device::with_mock(mock.clone());
    let stream = device.logs();

    mock.push_log(LogLevel::Warn, "overheating");

    let line = stream.recv_timeout(Duration::from_secs(1)).unwrap();
    assert_eq!(line.level, LogLevel::Warn);
    assert_eq!(line.text, "overheating");
}
```

## Testing async code

_A MockBox behind an AsyncDevice_

There's no `AsyncDevice::with_mock`: build a mocked `Device`, then call [`into_async`](/library/features/async.md). Drive the futures with [`block_on`](/library/guides/calls.md#block-on), so the test needs no async runtime. A [`silent`](/library/features/mock.md) box never answers, resolving the query to [`Err(Error::QueryTimeout)`](/library/types/errors.md).

#### EXAMPLE

```rust
use futures::executor::block_on;
use medius::{Device, Error, MockBox, Version};

let mock = MockBox::new().with_version(Version {
    proto_ver: 3, fw_major: 1, fw_minor: 2, fw_patch: 3, mac: [0; 6], name: "Loki".into(),
});
let device = Device::with_mock(mock).into_async();
let v = block_on(device.query_version())?;
assert_eq!((v.fw_major, v.fw_minor, v.fw_patch), (1, 2, 3));

// a silent box times out:
let device = Device::with_mock(MockBox::new().silent()).into_async();
assert!(matches!(block_on(device.query_version()).unwrap_err(), Error::QueryTimeout));
```
