diff --git a/Cargo.lock b/Cargo.lock
index ae90e371..6680d5dd 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -7372,6 +7372,15 @@ version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
 
+[[package]]
+name = "status-codes"
+version = "0.1.0"
+dependencies = [
+ "actix-web",
+ "env_logger",
+ "log",
+]
+
 [[package]]
 name = "string_cache"
 version = "0.8.7"
diff --git a/Cargo.toml b/Cargo.toml
index 6746d533..a6e3350b 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -66,6 +66,7 @@ members = [
    "websockets/chat",
    "websockets/echo-actorless",
    "websockets/echo",
+   "test/status-codes",
 ]
 
 [workspace.package]
diff --git a/test/status-codes/Cargo.toml b/test/status-codes/Cargo.toml
new file mode 100644
index 00000000..f56966b4
--- /dev/null
+++ b/test/status-codes/Cargo.toml
@@ -0,0 +1,11 @@
+[package]
+name = "status-codes"
+version = "0.1.0"
+publish.workspace = true
+edition.workspace = true
+rust-version.workspace = true
+
+[dependencies]
+actix-web.workspace = true
+env_logger.workspace = true
+log.workspace = true
diff --git a/test/status-codes/README.md b/test/status-codes/README.md
new file mode 100644
index 00000000..1137e421
--- /dev/null
+++ b/test/status-codes/README.md
@@ -0,0 +1,18 @@
+## Status Code
+
+The [StatusCode](https://docs.rs/actix-web/latest/actix_web/http/struct.StatusCode.html) trait contains the methods to test for the status codes.
+There are mainly two ways to test for the returning status code:
+
+1. Test for the exact status code (defined [here](https://docs.rs/actix-web/latest/actix_web/http/struct.StatusCode.html#impl-StatusCode-1))
+2. Test for the status code classes `informational`, `success`, `redirect`, `client_error` and `server_error` (defined [here](https://docs.rs/actix-web/latest/actix_web/http/struct.StatusCode.html#method.is_success))
+
+You can find the list of status codes definitions and their constants [here](https://docs.rs/http/0.2.9/src/http/status.rs.html#323-515).
+
+RFC 7231 [docs](https://datatracker.ietf.org/doc/html/rfc7231#section-6.2).
+
+## server
+
+```sh
+cd test/status-codes
+cargo test
+```
diff --git a/test/status-codes/src/main.rs b/test/status-codes/src/main.rs
new file mode 100644
index 00000000..493b4843
--- /dev/null
+++ b/test/status-codes/src/main.rs
@@ -0,0 +1,143 @@
+use actix_web::{get, middleware, App, HttpResponse, HttpServer, Responder};
+
+#[actix_web::main]
+async fn main() -> std::io::Result<()> {
+    env_logger::init_from_env(env_logger::Env::new().default_filter_or("info"));
+
+    log::info!("starting HTTP server at http://localhost:8080");
+
+    HttpServer::new(|| {
+        App::new()
+            .wrap(middleware::Logger::default())
+            .service(information_handler)
+            .service(success_handler)
+            .service(redirect_handler)
+            .service(client_error_handler)
+            .service(server_error_handler)
+    })
+    .bind(("127.0.0.1", 8080))?
+    .run()
+    .await
+}
+
+#[get("/")]
+async fn information_handler() -> impl Responder {
+    HttpResponse::Ok().finish()
+}
+
+#[get("/")]
+async fn success_handler() -> impl Responder {
+    HttpResponse::Ok().finish()
+}
+
+#[get("/")]
+async fn redirect_handler() -> impl Responder {
+    HttpResponse::TemporaryRedirect().finish()
+}
+
+#[get("/")]
+async fn client_error_handler() -> impl Responder {
+    HttpResponse::ImATeapot().finish()
+}
+
+#[get("/")]
+async fn server_error_handler() -> impl Responder {
+    HttpResponse::NotImplemented().finish()
+}
+
+#[cfg(test)]
+mod tests {
+    use actix_web::{dev::Service, http, test, App, Error};
+
+    use super::*;
+
+    #[actix_web::test]
+    /// Test informational status codes `1xx`
+    async fn test_informational() -> Result<(), Error> {
+        let app = App::new().service(information_handler);
+        let app = test::init_service(app).await;
+
+        let req = test::TestRequest::get().uri("/").to_request();
+        let resp = app.call(req).await?;
+
+        // This matches the exact value returned from `information_handler`
+        assert_eq!(resp.status(), http::StatusCode::CONTINUE);
+
+        // This matches all values considered _informational_ `1xx`
+        assert!(resp.status().is_informational());
+
+        Ok(())
+    }
+
+    #[actix_web::test]
+    /// Test success status codes `2xx`
+    async fn test_success() -> Result<(), Error> {
+        let app = App::new().service(success_handler);
+        let app = test::init_service(app).await;
+
+        let req = test::TestRequest::get().uri("/").to_request();
+        let resp = app.call(req).await?;
+
+        // This matches the exact value returned from `success_handler`
+        assert_eq!(resp.status(), http::StatusCode::OK);
+
+        // This matches all values considered _successfull_ `2xx`
+        assert!(resp.status().is_success());
+
+        Ok(())
+    }
+
+    #[actix_web::test]
+    /// Test redirect status codes `3xx`
+    async fn test_redirect() -> Result<(), Error> {
+        let app = App::new().service(redirect_handler);
+        let app = test::init_service(app).await;
+
+        let req = test::TestRequest::get().uri("/").to_request();
+        let resp = app.call(req).await?;
+
+        // This matches the exact value returned from `redirect_handler`
+        assert_eq!(resp.status(), http::StatusCode::TEMPORARY_REDIRECT);
+
+        // This matches all values considered _redirects_ `3xx`
+        assert!(resp.status().is_redirection());
+
+        Ok(())
+    }
+
+    #[actix_web::test]
+    /// Test client error status codes `4xx`
+    async fn test_client_error() -> Result<(), Error> {
+        let app = App::new().service(client_error_handler);
+        let app = test::init_service(app).await;
+
+        let req = test::TestRequest::get().uri("/").to_request();
+        let resp = app.call(req).await?;
+
+        // This matches the exact value returned from `client_error_handler`
+        assert_eq!(resp.status(), http::StatusCode::IM_A_TEAPOT);
+
+        // This matches all values considered _client error_ `4xx`
+        assert!(resp.status().is_client_error());
+
+        Ok(())
+    }
+
+    #[actix_web::test]
+    /// Test server error status codes `5xx`
+    async fn test_server_error() -> Result<(), Error> {
+        let app = App::new().service(server_error_handler);
+        let app = test::init_service(app).await;
+
+        let req = test::TestRequest::get().uri("/").to_request();
+        let resp = app.call(req).await?;
+
+        // This matches the exact value returned from `server_error_handler`
+        assert_eq!(resp.status(), http::StatusCode::NOT_IMPLEMENTED);
+
+        // This matches all values considered _server error_ `5xx`
+        assert!(resp.status().is_server_error());
+
+        Ok(())
+    }
+}