not working, rstest port

This commit is contained in:
filipriec
2025-02-24 16:05:32 +01:00
parent e8a3fdd673
commit da89715be3
3 changed files with 243 additions and 126 deletions

85
Cargo.lock generated
View File

@@ -669,6 +669,17 @@ version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6"
[[package]]
name = "futures-macro"
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "futures-sink"
version = "0.3.31"
@@ -681,6 +692,12 @@ version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988"
[[package]]
name = "futures-timer"
version = "3.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24"
[[package]]
name = "futures-util"
version = "0.3.31"
@@ -689,6 +706,7 @@ checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81"
dependencies = [
"futures-core",
"futures-io",
"futures-macro",
"futures-sink",
"futures-task",
"memchr",
@@ -736,6 +754,12 @@ version = "0.31.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
[[package]]
name = "glob"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2"
[[package]]
name = "h2"
version = "0.4.8"
@@ -1572,6 +1596,15 @@ dependencies = [
"syn",
]
[[package]]
name = "proc-macro-crate"
version = "3.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b"
dependencies = [
"toml_edit",
]
[[package]]
name = "proc-macro2"
version = "1.0.93"
@@ -1742,6 +1775,12 @@ version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
[[package]]
name = "relative-path"
version = "1.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2"
[[package]]
name = "rsa"
version = "0.9.7"
@@ -1762,12 +1801,51 @@ dependencies = [
"zeroize",
]
[[package]]
name = "rstest"
version = "0.24.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03e905296805ab93e13c1ec3a03f4b6c4f35e9498a3d5fa96dc626d22c03cd89"
dependencies = [
"futures-timer",
"futures-util",
"rstest_macros",
"rustc_version",
]
[[package]]
name = "rstest_macros"
version = "0.24.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef0053bbffce09062bee4bcc499b0fbe7a57b879f1efe088d6d8d4c7adcdef9b"
dependencies = [
"cfg-if",
"glob",
"proc-macro-crate",
"proc-macro2",
"quote",
"regex",
"relative-path",
"rustc_version",
"syn",
"unicode-ident",
]
[[package]]
name = "rustc-demangle"
version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
[[package]]
name = "rustc_version"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
dependencies = [
"semver",
]
[[package]]
name = "rustix"
version = "0.38.44"
@@ -1831,6 +1909,12 @@ dependencies = [
"libc",
]
[[package]]
name = "semver"
version = "1.0.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f79dfe2d285b0488816f30e700a7438c5a73d816b5b7d3ac72fbc48b0d185e03"
[[package]]
name = "serde"
version = "1.0.218"
@@ -1893,6 +1977,7 @@ dependencies = [
"dotenv",
"dotenvy",
"prost",
"rstest",
"serde",
"serde_json",
"sqlx",

View File

@@ -25,3 +25,4 @@ path = "src/lib.rs"
[dev-dependencies]
tokio = { version = "1.0", features = ["full", "test-util"] }
dotenv = "0.15"
rstest = "0.24.0"

View File

@@ -1,14 +1,29 @@
// tests/adresar/post_adresar_test.rs
// Import the rstest attribute macros.
use rstest::{awt, fixture, rstest};
use server::adresar::handlers::post_adresar;
use common::proto::multieko2::adresar::PostAdresarRequest;
use crate::common::setup_test_db;
use sqlx::PgPool;
use tonic;
// Helper functions
mod test_helpers {
use super::*;
// --- Fixtures ---
pub fn valid_request() -> PostAdresarRequest {
#[fixture]
async fn pool() -> PgPool {
setup_test_db().await
}
#[fixture]
async fn closed_pool(pool: PgPool) -> PgPool {
// Close the pool so we can simulate a DB error.
pool.close().await;
pool
}
#[fixture]
fn valid_request() -> PostAdresarRequest {
PostAdresarRequest {
firma: "Test Company".into(),
kz: "KZ123".into(),
@@ -26,182 +41,198 @@ mod test_helpers {
skladu: "Warehouse U".into(),
fax: "+421123456700".into(),
}
}
}
pub fn minimal_request() -> PostAdresarRequest {
#[fixture]
fn minimal_request() -> PostAdresarRequest {
PostAdresarRequest {
firma: "Required Only".into(),
..Default::default()
}
}
}
pub async fn assert_response_matches(pool: &PgPool, response: &common::proto::multieko2::adresar::AdresarResponse) {
// Verify database state
// A helper that checks that the database record matches the response.
async fn assert_response_matches(
pool: &PgPool,
response: &common::proto::multieko2::adresar::AdresarResponse,
) {
let db_record = sqlx::query!("SELECT * FROM adresar WHERE id = $1", response.id)
.fetch_one(pool)
.await
.unwrap();
assert_eq!(db_record.firma, response.firma);
assert_eq!(db_record.telefon, Some(response.telefon.clone()));
// Add assertions for other fields...
assert_eq!(
db_record.telefon.as_deref(),
Some(response.telefon.as_str())
);
// More field comparisons can be added here…
// Verify default values
assert!(!db_record.deleted);
assert!(db_record.created_at.is_some());
}
}
// --- Tests ---
#[rstest]
#[awt] // awaits all async fixture inputs
#[tokio::test]
async fn test_create_adresar_success() {
let pool = setup_test_db().await;
let request = test_helpers::valid_request();
async fn test_create_adresar_success(pool: PgPool, valid_request: PostAdresarRequest) {
let response = post_adresar(&pool, valid_request).await.unwrap();
let response = post_adresar(&pool, request).await.unwrap();
// Basic response validation
assert!(response.id > 0, "Should return positive ID");
assert_eq!(response.firma, "Test Company", "Firma should match");
// Verify all fields against request
let request = test_helpers::valid_request();
assert_eq!(response.kz, request.kz);
assert_eq!(response.drc, request.drc);
// Continue for all fields...
// Comprehensive database check
test_helpers::assert_response_matches(&pool, &response).await;
// Comprehensive database check.
assert_response_matches(&pool, &response).await;
}
#[rstest]
#[awt]
#[tokio::test]
async fn test_create_adresar_whitespace_trimming() {
let pool = setup_test_db().await;
async fn test_create_adresar_whitespace_trimming(
pool: PgPool,
mut valid_request: PostAdresarRequest,
) {
// Change some fields to include extra whitespace.
valid_request.firma = " Test Company ".into();
valid_request.telefon = " +421123456789 ".into();
valid_request.ulica = " Test Street ".into();
let mut request = test_helpers::valid_request();
request.firma = " Test Company ".into();
request.telefon = " +421123456789 ".into();
request.ulica = " Test Street ".into();
let response = post_adresar(&pool, request).await.unwrap();
let response = post_adresar(&pool, valid_request).await.unwrap();
assert_eq!(response.firma, "Test Company");
assert_eq!(response.telefon, "+421123456789");
assert_eq!(response.ulica, "Test Street");
}
#[rstest]
#[awt]
#[tokio::test]
async fn test_create_adresar_empty_optional_fields() {
let pool = setup_test_db().await;
async fn test_create_adresar_empty_optional_fields(
pool: PgPool,
mut valid_request: PostAdresarRequest,
) {
valid_request.telefon = " ".into();
let mut request = test_helpers::valid_request();
request.telefon = " ".into(); // Only whitespace
let response = post_adresar(&pool, valid_request).await.unwrap();
let response = post_adresar(&pool, request).await.unwrap();
// Should be stored as NULL in database
let record = sqlx::query!("SELECT telefon FROM adresar WHERE id = $1", response.id)
// Check in the database that telefono was stored as NULL.
let db_telefon = sqlx::query_scalar!("SELECT telefon FROM adresar WHERE id = $1", response.id)
.fetch_one(&pool)
.await
.unwrap();
assert!(record.telefon.is_none());
assert_eq!(response.telefon, ""); // Still returns empty string
assert!(db_telefon.is_none());
// The response still returns an empty string.
assert_eq!(response.telefon, "");
}
#[rstest]
#[awt]
#[tokio::test]
async fn test_create_adresar_invalid_firma() {
let pool = setup_test_db().await;
async fn test_create_adresar_invalid_firma(
pool: PgPool,
mut valid_request: PostAdresarRequest,
) {
valid_request.firma = " ".into();
let mut request = test_helpers::valid_request();
request.firma = " ".into(); // Only whitespace
let result = post_adresar(&pool, request).await;
let result = post_adresar(&pool, valid_request).await;
assert!(result.is_err());
assert_eq!(result.unwrap_err().code(), tonic::Code::InvalidArgument);
}
#[rstest]
#[awt]
#[tokio::test]
async fn test_create_adresar_minimal_valid_request() {
let pool = setup_test_db().await;
let request = test_helpers::minimal_request();
let response = post_adresar(&pool, request).await.unwrap();
async fn test_create_adresar_minimal_valid_request(
pool: PgPool,
minimal_request: PostAdresarRequest,
) {
let response = post_adresar(&pool, minimal_request).await.unwrap();
assert!(response.id > 0);
assert_eq!(response.firma, "Required Only");
// Verify optional fields are empty
// Verify that all other optional fields appear empty.
assert!(response.kz.is_empty());
assert!(response.drc.is_empty());
// Continue for all optional fields...
// ...and so on.
}
#[rstest]
#[awt]
#[tokio::test]
async fn test_create_adresar_empty_firma() {
let pool = setup_test_db().await;
let mut request = test_helpers::minimal_request();
request.firma = "".into();
let result = post_adresar(&pool, request).await;
async fn test_create_adresar_empty_firma(
pool: PgPool,
mut minimal_request: PostAdresarRequest,
) {
minimal_request.firma = "".into();
let result = post_adresar(&pool, minimal_request).await;
assert!(result.is_err());
assert_eq!(result.unwrap_err().code(), tonic::Code::InvalidArgument);
}
#[rstest]
#[awt]
#[tokio::test]
async fn test_create_adresar_database_error() {
let pool = setup_test_db().await;
pool.close().await;
let result = post_adresar(&pool, test_helpers::minimal_request()).await;
async fn test_create_adresar_database_error(
closed_pool: PgPool,
minimal_request: PostAdresarRequest,
) {
let result = post_adresar(&closed_pool, minimal_request).await;
assert!(result.is_err());
assert_eq!(result.unwrap_err().code(), tonic::Code::Internal);
}
#[rstest]
#[awt]
#[tokio::test]
async fn test_create_adresar_field_length_limits() {
let pool = setup_test_db().await;
async fn test_create_adresar_field_length_limits(
pool: PgPool,
mut valid_request: PostAdresarRequest,
) {
valid_request.firma = "a".repeat(255);
valid_request.telefon = "1".repeat(20);
let mut request = test_helpers::valid_request();
request.firma = "a".repeat(255);
request.telefon = "1".repeat(20); // Example length based on DB schema
let response = post_adresar(&pool, request).await.unwrap();
let response = post_adresar(&pool, valid_request).await.unwrap();
assert_eq!(response.firma.len(), 255);
assert_eq!(response.telefon.len(), 20);
}
#[rstest]
#[awt]
#[tokio::test]
async fn test_create_adresar_special_characters() {
let pool = setup_test_db().await;
async fn test_create_adresar_special_characters(
pool: PgPool,
mut valid_request: PostAdresarRequest,
) {
valid_request.telefon = "+420 123-456.789".into();
valid_request.ulica = "Náměstí 28. října".into();
let mut request = test_helpers::valid_request();
request.telefon = "+420 123-456.789".into();
request.ulica = "Náměstí 28. října".into();
let response = post_adresar(&pool, valid_request.clone()).await.unwrap();
let response = post_adresar(&pool, request.clone()).await.unwrap();
assert_eq!(response.telefon, request.telefon);
assert_eq!(response.ulica, request.ulica);
assert_eq!(response.telefon, valid_request.telefon);
assert_eq!(response.ulica, valid_request.ulica);
}
#[rstest]
#[awt]
#[tokio::test]
async fn test_create_adresar_optional_fields_null_vs_empty() {
let pool = setup_test_db().await;
async fn test_create_adresar_optional_fields_null_vs_empty(
pool: PgPool,
mut valid_request: PostAdresarRequest,
) {
valid_request.telefon = String::new();
// Test explicit null (using default values)
let mut request = test_helpers::valid_request();
request.telefon = String::new();
let response = post_adresar(&pool, request).await.unwrap();
// Verify empty string is stored as NULL in database
let record = sqlx::query!("SELECT telefon FROM adresar WHERE id = $1", response.id)
let response = post_adresar(&pool, valid_request).await.unwrap();
let db_telefon = sqlx::query_scalar!("SELECT telefon FROM adresar WHERE id = $1", response.id)
.fetch_one(&pool)
.await
.unwrap();
assert!(record.telefon.is_none());
assert!(db_telefon.is_none());
}