Add tests with passing empty string value

This commit is contained in:
Yurii Motov
2026-02-06 16:59:18 +01:00
parent c733bab825
commit f49f65aa16
4 changed files with 210 additions and 59 deletions

View File

@@ -261,7 +261,9 @@ def test_nullable_required_no_embed_missing(path: str):
),
],
)
def test_nullable_required_no_embed_pass_empty_dict(path: str, msg: str, error_type: str):
def test_nullable_required_no_embed_pass_empty_dict(
path: str, msg: str, error_type: str
):
client = TestClient(app)
response = client.post(path, json={})
assert response.status_code == 422
@@ -344,20 +346,25 @@ def test_nullable_required_no_embed_pass_null(path: str):
"/model-nullable-required",
],
)
def test_nullable_required_pass_value(path: str):
@pytest.mark.parametrize(
"values",
[
{"int_val": "1", "str_val": "test", "list_val": ["1", "2"]},
{"int_val": "0", "str_val": "", "list_val": ["0"]},
],
)
def test_nullable_required_pass_value(path: str, values: dict[str, Any]):
client = TestClient(app)
with patch(f"{__name__}.convert", Mock(wraps=convert)) as mock_convert:
response = client.post(
path, json={"int_val": "1", "str_val": "test", "list_val": ["1", "2"]}
)
response = client.post(path, json=values)
assert mock_convert.call_count == 3, "Validator should be called for each field"
assert response.status_code == 200, response.text
assert response.json() == {
"int_val": 1,
"str_val": "test",
"list_val": [1, 2],
"int_val": int(values["int_val"]),
"str_val": values["str_val"],
"list_val": [int(v) for v in values["list_val"]],
"fields_set": IsOneOf(
None, IsList("int_val", "str_val", "list_val", check_order=False)
),
@@ -368,6 +375,7 @@ def test_nullable_required_pass_value(path: str):
("path", "value"),
[
("/nullable-required-str", "test"),
("/nullable-required-str", ""),
("/nullable-required-int", 1),
("/nullable-required-list", [1, 2]),
],
@@ -685,20 +693,25 @@ def test_nullable_non_required_no_embed_pass_null(path: str):
"/model-nullable-non-required",
],
)
def test_nullable_non_required_pass_value(path: str):
@pytest.mark.parametrize(
"values",
[
{"int_val": "1", "str_val": "test", "list_val": ["1", "2"]},
{"int_val": "0", "str_val": "", "list_val": ["0"]},
],
)
def test_nullable_non_required_pass_value(path: str, values: dict[str, Any]):
client = TestClient(app)
with patch(f"{__name__}.convert", Mock(wraps=convert)) as mock_convert:
response = client.post(
path, json={"int_val": 1, "str_val": "test", "list_val": [1, 2]}
)
response = client.post(path, json=values)
assert mock_convert.call_count == 3, "Validator should be called for each field"
assert response.status_code == 200, response.text
assert response.json() == {
"int_val": 1,
"str_val": "test",
"list_val": [1, 2],
"int_val": int(values["int_val"]),
"str_val": values["str_val"],
"list_val": [int(v) for v in values["list_val"]],
"fields_set": IsOneOf(
None, IsList("int_val", "str_val", "list_val", check_order=False)
),
@@ -709,6 +722,7 @@ def test_nullable_non_required_pass_value(path: str):
("path", "value"),
[
("/nullable-non-required-str", "test"),
("/nullable-non-required-str", ""),
("/nullable-non-required-int", 1),
("/nullable-non-required-list", [1, 2]),
],
@@ -1033,20 +1047,25 @@ def test_nullable_with_non_null_default_no_embed_pass_null(path: str):
"/model-nullable-with-non-null-default",
],
)
def test_nullable_with_non_null_default_pass_value(path: str):
@pytest.mark.parametrize(
"values",
[
{"int_val": "1", "str_val": "test", "list_val": ["1", "2"]},
{"int_val": "0", "str_val": "", "list_val": ["0"]},
],
)
def test_nullable_with_non_null_default_pass_value(path: str, values: dict[str, Any]):
client = TestClient(app)
with patch(f"{__name__}.convert", Mock(wraps=convert)) as mock_convert:
response = client.post(
path, json={"int_val": "1", "str_val": "test", "list_val": ["1", "2"]}
)
response = client.post(path, json=values)
assert mock_convert.call_count == 3, "Validator should be called for each field"
assert response.status_code == 200, response.text
assert response.json() == {
"int_val": 1,
"str_val": "test",
"list_val": [1, 2],
"int_val": int(values["int_val"]),
"str_val": values["str_val"],
"list_val": [int(v) for v in values["list_val"]],
"fields_set": IsOneOf(
None, IsList("int_val", "str_val", "list_val", check_order=False)
),
@@ -1057,6 +1076,7 @@ def test_nullable_with_non_null_default_pass_value(path: str):
("path", "value"),
[
("/nullable-with-non-null-default-str", "test"),
("/nullable-with-non-null-default-str", ""),
("/nullable-with-non-null-default-int", 1),
("/nullable-with-non-null-default-list", [1, 2]),
],

View File

@@ -130,19 +130,25 @@ def test_nullable_required_missing(path: str):
"/model-nullable-required",
],
)
def test_nullable_required_pass_value(path: str):
@pytest.mark.parametrize(
"values",
[
{"int_val": "1", "str_val": "test"},
{"int_val": "0", "str_val": ""},
],
)
def test_nullable_required_pass_value(path: str, values: dict[str, str]):
client = TestClient(app)
client.cookies.set("int_val", "1")
client.cookies.set("str_val", "test")
client.cookies.set("int_val", values["int_val"])
client.cookies.set("str_val", values["str_val"])
with patch(f"{__name__}.convert", Mock(wraps=convert)) as mock_convert:
response = client.get(path)
assert mock_convert.call_count == 2, "Validator should be called for each field"
assert response.status_code == 200, response.text
assert response.json() == {
"int_val": 1,
"str_val": "test",
"int_val": int(values["int_val"]),
"str_val": values["str_val"],
"fields_set": IsOneOf(None, IsList("int_val", "str_val", check_order=False)),
}
@@ -255,10 +261,17 @@ def test_nullable_non_required_missing(path: str):
"/model-nullable-non-required",
],
)
def test_nullable_non_required_pass_value(path: str):
@pytest.mark.parametrize(
"values",
[
{"int_val": "1", "str_val": "test"},
{"int_val": "0", "str_val": ""},
],
)
def test_nullable_non_required_pass_value(path: str, values: dict[str, str]):
client = TestClient(app)
client.cookies.set("int_val", "1")
client.cookies.set("str_val", "test")
client.cookies.set("int_val", values["int_val"])
client.cookies.set("str_val", values["str_val"])
with patch(f"{__name__}.convert", Mock(wraps=convert)) as mock_convert:
response = client.get(path)
@@ -266,8 +279,8 @@ def test_nullable_non_required_pass_value(path: str):
assert mock_convert.call_count == 2, "Validator should be called for each field"
assert response.status_code == 200, response.text
assert response.json() == {
"int_val": 1,
"str_val": "test",
"int_val": int(values["int_val"]),
"str_val": values["str_val"],
"fields_set": IsOneOf(None, IsList("int_val", "str_val", check_order=False)),
}
@@ -385,10 +398,17 @@ def test_nullable_with_non_null_default_missing(path: str):
"/model-nullable-with-non-null-default",
],
)
def test_nullable_with_non_null_default_pass_value(path: str):
@pytest.mark.parametrize(
"values",
[
{"int_val": "1", "str_val": "test"},
{"int_val": "0", "str_val": ""},
],
)
def test_nullable_with_non_null_default_pass_value(path: str, values: dict[str, str]):
client = TestClient(app)
client.cookies.set("int_val", "1")
client.cookies.set("str_val", "test")
client.cookies.set("int_val", values["int_val"])
client.cookies.set("str_val", values["str_val"])
with patch(f"{__name__}.convert", Mock(wraps=convert)) as mock_convert:
response = client.get(path)
@@ -396,7 +416,7 @@ def test_nullable_with_non_null_default_pass_value(path: str):
assert mock_convert.call_count == 2, "Validator should be called for each field"
assert response.status_code == 200, response.text
assert response.json() == {
"int_val": 1,
"str_val": "test",
"int_val": int(values["int_val"]),
"str_val": values["str_val"],
"fields_set": IsOneOf(None, IsList("int_val", "str_val", check_order=False)),
}

View File

@@ -195,6 +195,38 @@ def test_nullable_required_pass_value(path: str):
}
@pytest.mark.parametrize(
"path",
[
"/nullable-required",
"/model-nullable-required",
],
)
def test_nullable_required_pass_empty_str_to_str_val(path: str):
client = TestClient(app)
with patch(f"{__name__}.convert", Mock(wraps=convert)) as mock_convert:
response = client.get(
path,
headers=[
("int-val", "1"),
("str-val", ""),
("list-val", "1"),
],
)
assert mock_convert.call_count == 3, "Validator should be called for each field"
assert response.status_code == 200, response.text
assert response.json() == {
"int_val": 1,
"str_val": "",
"list_val": [1],
"fields_set": IsOneOf(
None, IsList("int_val", "str_val", "list_val", check_order=False)
),
}
# =====================================================================================
# Nullable with default=None
@@ -356,6 +388,38 @@ def test_nullable_non_required_pass_value(path: str):
}
@pytest.mark.parametrize(
"path",
[
"/nullable-non-required",
"/model-nullable-non-required",
],
)
def test_nullable_non_required_pass_empty_str_to_str_val(path: str):
client = TestClient(app)
with patch(f"{__name__}.convert", Mock(wraps=convert)) as mock_convert:
response = client.get(
path,
headers=[
("int-val", "1"),
("str-val", ""),
("list-val", "1"),
],
)
assert mock_convert.call_count == 3, "Validator should be called for each field"
assert response.status_code == 200, response.text
assert response.json() == {
"int_val": 1,
"str_val": "",
"list_val": [1],
"fields_set": IsOneOf(
None, IsList("int_val", "str_val", "list_val", check_order=False)
),
}
# =====================================================================================
# Nullable with not-None default
@@ -527,3 +591,35 @@ def test_nullable_with_non_null_default_pass_value(path: str):
None, IsList("int_val", "str_val", "list_val", check_order=False)
),
}
@pytest.mark.parametrize(
"path",
[
"/nullable-with-non-null-default",
"/model-nullable-with-non-null-default",
],
)
def test_nullable_with_non_null_default_pass_empty_str_to_str_val(path: str):
client = TestClient(app)
with patch(f"{__name__}.convert", Mock(wraps=convert)) as mock_convert:
response = client.get(
path,
headers=[
("int-val", "1"),
("str-val", ""),
("list-val", "1"),
],
)
assert mock_convert.call_count == 3, "Validator should be called for each field"
assert response.status_code == 200, response.text
assert response.json() == {
"int_val": 1,
"str_val": "",
"list_val": [1],
"fields_set": IsOneOf(
None, IsList("int_val", "str_val", "list_val", check_order=False)
),
}

View File

@@ -155,20 +155,25 @@ def test_nullable_required_missing(path: str):
"/model-nullable-required",
],
)
def test_nullable_required_pass_value(path: str):
@pytest.mark.parametrize(
"values",
[
{"int_val": "1", "str_val": "test", "list_val": ["1", "2"]},
{"int_val": "0", "str_val": "", "list_val": ["0"]},
],
)
def test_nullable_required_pass_value(path: str, values: dict[str, Any]):
client = TestClient(app)
with patch(f"{__name__}.convert", Mock(wraps=convert)) as mock_convert:
response = client.get(
path, params={"int_val": "1", "str_val": "test", "list_val": ["1", "2"]}
)
response = client.get(path, params=values)
assert mock_convert.call_count == 3, "Validator should be called for each field"
assert response.status_code == 200, response.text
assert response.json() == {
"int_val": 1,
"str_val": "test",
"list_val": [1, 2],
"int_val": int(values["int_val"]),
"str_val": values["str_val"],
"list_val": [int(v) for v in values["list_val"]],
"fields_set": IsOneOf(
None, IsList("int_val", "str_val", "list_val", check_order=False)
),
@@ -303,20 +308,25 @@ def test_nullable_non_required_missing(path: str):
"/model-nullable-non-required",
],
)
def test_nullable_non_required_pass_value(path: str):
@pytest.mark.parametrize(
"values",
[
{"int_val": "1", "str_val": "test", "list_val": ["1", "2"]},
{"int_val": "0", "str_val": "", "list_val": ["0"]},
],
)
def test_nullable_non_required_pass_value(path: str, values: dict[str, Any]):
client = TestClient(app)
with patch(f"{__name__}.convert", Mock(wraps=convert)) as mock_convert:
response = client.get(
path, params={"int_val": "1", "str_val": "test", "list_val": ["1", "2"]}
)
response = client.get(path, params=values)
assert mock_convert.call_count == 3, "Validator should be called for each field"
assert response.status_code == 200, response.text
assert response.json() == {
"int_val": 1,
"str_val": "test",
"list_val": [1, 2],
"int_val": int(values["int_val"]),
"str_val": values["str_val"],
"list_val": [int(v) for v in values["list_val"]],
"fields_set": IsOneOf(
None, IsList("int_val", "str_val", "list_val", check_order=False)
),
@@ -463,20 +473,25 @@ def test_nullable_with_non_null_default_missing(path: str):
"/model-nullable-with-non-null-default",
],
)
def test_nullable_with_non_null_default_pass_value(path: str):
@pytest.mark.parametrize(
"values",
[
{"int_val": "1", "str_val": "test", "list_val": ["1", "2"]},
{"int_val": "0", "str_val": "", "list_val": ["0"]},
],
)
def test_nullable_with_non_null_default_pass_value(path: str, values: dict[str, Any]):
client = TestClient(app)
with patch(f"{__name__}.convert", Mock(wraps=convert)) as mock_convert:
response = client.get(
path, params={"int_val": "1", "str_val": "test", "list_val": ["1", "2"]}
)
response = client.get(path, params=values)
assert mock_convert.call_count == 3, "Validator should be called for each field"
assert response.status_code == 200, response.text
assert response.json() == {
"int_val": 1,
"str_val": "test",
"list_val": [1, 2],
"int_val": int(values["int_val"]),
"str_val": values["str_val"],
"list_val": [int(v) for v in values["list_val"]],
"fields_set": IsOneOf(
None, IsList("int_val", "str_val", "list_val", check_order=False)
),