I'm working on a flask application and I'm using marshmallow to validate and "cast" values when someone hit an endpoint, everything works as expected but now I need to write some unit tests for the marshmallow schema that I wrote. Some methods have @validates
and @post_load
and other don't
class MultipartFileSchema(ma.Schema):
data = ma.fields.Raw(required=True, load_only=True)
accepted_fields = ma.fields.List(ma.fields.Dict, required=False, default=[])
logger = logging.getLogger(__name__)
@validates("data")
def is_file_valid(self, files: FileStorage) -> None:
"""Check if the file uploaded is valid"""
self.logger.info("Validating CSV file attached to the request in 'data' field")
if isinstance(files, FileStorage):
# Mypy is complaining about the following line, it says that that files is None type,
# but it is not, it is a FileStorage object, since it passes the isinstance check
if files.filename.endswith(".csv"): # type: ignore
content = files.readline().decode("utf-8")
if content:
for field in content.split(","):
if not self.is_sp_key_valid(field.split(".")):
raise ValidationError(message="Invalid fields")
else:
raise ValidationError(message="Invalid/Missing file content")
files.seek(0)
else:
raise ValidationError("Invalid file type")
elif not isinstance(files, FileStorage):
raise ValidationError("Invalid/Missing file content")
@post_load
def load_file(self, files, many, **kwargs) -> dict:
"""Load the file and return a dict with the file content"""
self.logger.info("Converting CSV file to a dict")
files["accepted_fields"] = []
content = StringIO(files["data"].read().decode("utf-8"))
csv_raw_data = csv.DictReader(content, delimiter=",")
for row in csv_raw_data:
service_provider_raw: dict[str, dict[str, Union[str, bool, int]]] = {}
for key, value in row.items():
key_list = key.split(".")
sp_main_key = key_list[0]
sp_sub_key = key_list[1]
if sp_main_key not in service_provider_raw:
service_provider_raw[sp_main_key] = {}
service_provider_raw[sp_main_key][sp_sub_key] = value
service_provider = CreateUpdateServiceProviderSchema().load(service_provider_raw)
files["accepted_fields"].append(service_provider)
return files
def is_sp_sub_key_valid(self, sp_main_key: str, sp_sub_key: str) -> bool:
"""Check if the sub key in a service_provider object is valid"""
self.logger.info("Validating sub keys in service_provider object")
valid = False
if sp_main_key == "general_fields":
valid = sp_sub_key in ["name", "service_provider_type", "status"]
elif sp_main_key == "primary_contact":
valid = sp_sub_key in ["email_address", "phone_number"]
elif sp_main_key == "address":
valid = sp_sub_key in [
"street",
"city",
"state",
"country",
"zip_code",
]
return valid
def is_sp_key_valid(self, key_list: list[str]) -> bool:
"""Check if the key in a service_provider object is valid"""
self.logger.info("Validating dict is a valid service_provider object")
valid = True
if len(key_list) == 2:
sp_main_key = key_list[0].strip()
sp_sub_key = key_list[1].strip()
if not self.is_sp_sub_key_valid(sp_main_key, sp_sub_key):
valid = False
else:
valid = False
return valid
so the question is how can I test those methods individully, specially those with decorator? thanks in advance for the help! :-)