Git Product home page Git Product logo

mockmail's Introduction

Mockmail

Implementation of mock service for testing emails in Rust using

  • enums,
  • generics, and
  • trait objects.

You can find the relevant code in the identically named workspaces above.

Using enums

Our email service should take either a RealClient which sends a real email in production or a MockClient which sends a mock email while testing. An enum with a Real and a Mock variant is a natural way to achieve this:

pub enum EmailClient {
    Real(RealClient),
    Mock(MockClient),
}

We can improve on this by using conditional compilation on the Mock variant:

pub enum EmailClient {
    Real(RealClient),
    #[cfg(test)]
    Mock(MockClient),
}

This way the additional Mock variant does compile for unit testing. However, the Real variant is the only variant for a release build, leading to (slightly) better runtime performance.

Finally, our service takes an EmailClient as follows:

pub async fn email_service(client: &EmailClient) -> Result<(), anyhow::Error> {
    let email = Email::default();
    client.send(email).await
}

where EmailClient is either a RealClient or a MockClient.

Using traits

Instead of enums you can use traits as well:

#[async_trait]
pub trait SendEmail {
    async fn send(&self, email: Email) -> Result<(), anyhow::Error>;
}

The trait has to be implemented for the RealClient as well as the MockClient and can then be used via

  1. generics (static dispatch), or
  2. trait objects (dynamic dispatch).

On the one hand, static dispatch has better runtime performance through monomorphization while dynamic dispatch has a slight performance overhead through a vtable lookup. On the other hand, static dispatch is leading to a sligthly longer compilation time and larger binary size compared to dynamic dispatch.

Using generics

In this case, the service is generic over parameter T with trait bound SendEmail:

pub async fn email_service<T: SendEmail>(client: &T) -> Result<(), anyhow::Error> {
    let email = Email::default();
    client.send(email).await
}

A more tense and in this case equivalent notation uses the impl keyword:

pub async fn email_service(client: &impl SendEmail) -> Result<(), anyhow::Error> {
    let email = Email::default();
    client.send(email).await
}

Using trait objects

Using dynamic dispatch, the trait object is denoted by the dyn keyword:

pub async fn email_service(client: &dyn SendEmail) -> Result<(), anyhow::Error> {
    let email = Email::default();
    client.send(email).await
}

Testing

Run tests in all workspaces:

cargo test --workspace

Run tests in all workspaces and show output:

cargo test --workspace -- --show-output

mockmail's People

Contributors

quambene avatar

Stargazers

 avatar  avatar  avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.