✅ Add tests for nullable parameters and defaults by YuriiMotov · Pull Request #14829 · fastapi/fastapi

Description

There are currently several issues around nullable parameters and parameters with defaults:

  • inability to distinguish explicitly passed values from defaults (if no value received, the default value is passed to parameter validator)
  • parameters declared as Pydantic model behave different from non-model parameters (different behavior and error messages)
    • empty strings are not replaced by None for Form parameters declared as Pydantic model - this leads to validation error for optional int parameter when empty string is submitted
    • title of Header parameters contains hyphens for non-model parameters (for model parameters hyphens are replaced by whitespaces)
    • for Header parameters declared as Pydantic model, field names use underscore instead of hyphens in error response
    • null values are treated as missing value for non-Model Body parameters
    • missing or invalid body value results in different errors for parameters declared as Body model and parameters declared as several Body parameters
  • if the default value is None, it's not reflected in schema
  • Handling of empty strings for Form parameters

doesn’t seem to work correctly - None values are then being dropped. So, it’s equal to not providing the value. But people want to be able to distinguish between no value and explicitly passed empty string (ecplicit None for nullable parameter)

  • null-value body is treated as missing (it’s valid body in latest specs)
  • It’s possible to specify default value for bytes File parameter, but it doesn’t work (raises AttributeError as FastAPI attempts to use it as file object)

This PR is intended to expose these issues for different types of parameters.

Tests structure

Tests for each type of parameter (Query, Form, Body, etc..) in general follow the pattern:

  • For different default values ( 1 - without default value (nullable required); 2 - default is None (optional); 3 - default is not None):
    • Tests for: non-model parameters and parameters declared as Pydantic model (for Body also have single parameters with embed=False)
      • Declare parameters with different field types (all nullable): str, int, list[int]
      • Test:
        • openapi schema
        • request with missing parameter values (and with missing body in case of Body)
        • request with explicit null values (and with null-body in case of Body) when it's possibe
        • request with non-default value
      • In tests check:
        • Data passed to field validator is as expected (checked using BeforeValidator). Also check fields_set for parameters declared as model
        • Schema and error messages are correct and equal in case of parameters declared as model and non-model parameters
        • Values after validation are correct

Related discussions and PRs

Details

Open questions

  • Should we prohibit default value for File parameters? I can't come up with use case when it might be needed. And it doesn't work currently
  • For Form fields, how should we treat the empty string values?