Skip to content

Commit ce09626

Browse files
committed
test: 🚨 Also add tests for model validation
1 parent 6c3a53f commit ce09626

File tree

2 files changed

+93
-1
lines changed

2 files changed

+93
-1
lines changed

‎pydantic_async_validation/utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ def make_generic_model_validator(validator_func: Callable) -> Callable:
121121
)
122122

123123

124-
all_model_validator_kwargs = {'validator'}
124+
all_model_validator_kwargs = {'config'}
125125

126126

127127
def generic_model_validator_wrapper(

‎tests/test_model_validators.py

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
from typing import Any, Dict, List
2+
3+
import pydantic
4+
import pytest
5+
from pydantic.errors import PydanticUserError
6+
7+
from pydantic_async_validation import AsyncValidationModelMixin, async_model_validator
8+
from pydantic_async_validation.validators import ValidationInfo
9+
10+
11+
class SomethingModel(AsyncValidationModelMixin, pydantic.BaseModel):
12+
name: str
13+
age: int
14+
15+
@async_model_validator()
16+
async def validate_name(self) -> None:
17+
if self.name == "invalid":
18+
raise ValueError("Invalid name")
19+
20+
21+
@pytest.mark.asyncio
22+
async def test_async_validation_raises_no_issues():
23+
instance = SomethingModel(name="valid", age=1)
24+
await instance.model_async_validate()
25+
26+
27+
@pytest.mark.asyncio
28+
async def test_async_validation_raises_when_validation_fails():
29+
instance = SomethingModel(name="invalid", age=1)
30+
with pytest.raises(pydantic.ValidationError):
31+
await instance.model_async_validate()
32+
33+
34+
@pytest.mark.asyncio
35+
async def test_all_field_validator_combinations_are_valid():
36+
class OtherModel(AsyncValidationModelMixin, pydantic.BaseModel):
37+
name: str
38+
39+
@async_model_validator()
40+
async def validate_name_1(self) -> None: pass
41+
42+
@async_model_validator()
43+
async def validate_name_2(self, config: ValidationInfo) -> None: pass
44+
45+
instance = OtherModel(name="valid")
46+
await instance.model_async_validate()
47+
48+
49+
@pytest.mark.asyncio
50+
async def test_invalid_validators_are_prohibited():
51+
with pytest.raises(PydanticUserError):
52+
class OtherModel1(AsyncValidationModelMixin, pydantic.BaseModel):
53+
name: str
54+
55+
@async_model_validator()
56+
async def validate_name(self, uses_value_or_anything: Any) -> None: pass
57+
58+
59+
@pytest.mark.asyncio
60+
async def test_async_validation_may_get_extra_details():
61+
class OtherModel(AsyncValidationModelMixin, pydantic.BaseModel):
62+
name: str
63+
64+
@async_model_validator(some="thing")
65+
async def validate_name(self, config: ValidationInfo) -> None:
66+
assert config.extra == {"some": "thing"}
67+
68+
instance = OtherModel(name="valid")
69+
await instance.model_async_validate()
70+
71+
72+
@pytest.mark.asyncio
73+
async def test_async_validation_will_call_sub_model_validation():
74+
class OtherModel(AsyncValidationModelMixin, pydantic.BaseModel):
75+
something: SomethingModel
76+
somethings: List[SomethingModel]
77+
somethings_by_name: Dict[str, SomethingModel]
78+
79+
instance = OtherModel(
80+
something=SomethingModel(name="invalid", age=1),
81+
somethings=[SomethingModel(name="invalid", age=1)],
82+
somethings_by_name={"some": SomethingModel(name="invalid", age=1)},
83+
)
84+
with pytest.raises(pydantic.ValidationError) as O_o:
85+
await instance.model_async_validate()
86+
87+
assert len(O_o.value.errors()) == 3
88+
assert {e['loc'] for e in O_o.value.errors()} == {
89+
('something', '__root__'),
90+
('somethings', 0, '__root__'),
91+
('somethings_by_name', 'some', '__root__'),
92+
}

0 commit comments

Comments
 (0)