4

I have a struct that works as a postmaster for a server application: since I don't know how many clients will connect I have the postmaster listen on a socket and start a new struct with business logic whenever a client opens a connection.

But this means I don't know how to implement integration tests for the Postmaster. There is a public "main" method that hangs indefinitely while waiting for connections:

#[tokio::main]
  pub async fn start(self) -> Result<(), GenericError> {
    // https://stackoverflow.com/a/55874334/70600
    let mut this = self;
    loop {
      let tmp = this.configuration.clone().hostaddr();
      println!("{:?}", tmp);
      let listener = TcpListener::bind(tmp).await?;
      match listener.accept().await {
        Ok((stream, _addr)) => {
          let backend = Backend::new(&this.configuration, stream);
          this.backends.push(backend);
        }
        Err(e) => todo!("Log error accepting client connection."),
      }
    }
    Ok(())
  }

This is my test:

#[test]
fn test_server_default_configuration() {
  let postmaster = Postmaster::default();
  let started = postmaster.start();
  assert!(started.is_ok())
}

Except the assert is obviously never reached. How can I test this async code?

ruipacheco
  • 15,025
  • 19
  • 82
  • 138
  • The simplest option is to start the postmaster in a separate thread, connect to it, and give it some commands. For example: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=7dc4643c6c63039a0334fdebcd5fb4d2 – user4815162342 Nov 17 '21 at 18:05
  • And once those echoed back I would know it worked. Turn that into an answer? – ruipacheco Nov 17 '21 at 18:23

1 Answers1

4

You can start the postmaster in a separate thread, connect to it, and give it some commands, and check the responses:

#[test]
fn test_server_default_configuration() {
    let postmaster = Postmaster::default();
    let thr = std::thread::spawn(move || postmaster.start());
    // connect to the configured address, test the responses...
    // ...
    // finally, send the postmaster a "quit" command
    let result = thr.join().unwrap();
    assert!(result.is_ok())
}
user4815162342
  • 141,790
  • 18
  • 296
  • 355