thomasarmel / socket-server-mocker

Mock socket server in Rust, for testing various network clients.
https://crates.io/crates/socket-server-mocker
MIT License
0 stars 2 forks source link

Rethinking `Instruction` approach #15

Open nyurik opened 6 days ago

nyurik commented 6 days ago

I keep thinking how this crate can be made more similar to the mockito API, so wanted to start a discussion here. These are just ideas, looking for feedback.

The main difference between TCP, UDP, and HTTP protocols is that HTTP is a request/response, while TCP and especially UDP are bi-directional. With HTTP, it is possible to define a "mock" = "wait for the request, verify it, respond with content, assert it has completed":

let mut server = mockito::Server::new();

// Wait for a request, which must ask for `GET /hello` and with
// request header `foo=bar`, and respond with content:
let mock = server.mock("GET", "/hello")
      .match_header("foo", "bar")
      .with_status(201)
      .with_header("content-type", "text/plain")
      .with_body("world")
      .create();

// actual logic for a client to fetch needed data
...

// ensure the server got the request and responded to it 
mock.assert();

While this makes an easy to use API, let's think how a similar approach may work with TCP/UDP:

// respond after getting the specific content
let mock = server
      .on_data(b"abc")
      .send(b"xyz");

// make sure the server gets "abc", but do not respond at all
let mock = server
      .on_data(b"abc")
      .ignore();

// send "xyz" after waiting for some time, asserts that inbound buffer is empty
let mock = server
      .after(Duration::from_secs(1))
      .send(b"xyz");

// accept a certain number of bytes, and run a custom handler
let mock = server
      .after_n_bytes(10)
      .run(|v| validate_bytes(v)); // v is a &[u8], respond with Vec<u8>, can be empty

// This will close connection once the previous steps have completed.
// Is this needed?
let mock = server.close_on_done();

Just like with Mockito, user can use mock.assert() to verify that the specific step has successfully executed. Server options will have a assert_on_drop flag to ensure each step has ran. We could set it to true by default even though Mockito sets it to false.

thomasarmel commented 3 days ago

That's a good idea :smile: .

As I'm quite busy nowadays, would you mind working on it?