Browse Source

Fixed tests having incorrect ids. Fixed an inconsistent results for tests which check websocket-scoped teardowns before the teardown actually happened on the server side.

pull/12529/head
Nir Schulman 9 months ago
parent
commit
3b27561d3d
  1. 24
      tests/test_lifespan_scoped_dependencies/test_dependency_overrides.py
  2. 45
      tests/test_lifespan_scoped_dependencies/test_endpoint_usage.py
  3. 4
      tests/test_lifespan_scoped_dependencies/testing_utilities.py

24
tests/test_lifespan_scoped_dependencies/test_dependency_overrides.py

@ -13,6 +13,8 @@ from fastapi import (
Header, Header,
Path, Path,
Query, Query,
Request,
WebSocket,
) )
from fastapi.exceptions import DependencyScopeConflict from fastapi.exceptions import DependencyScopeConflict
from fastapi.params import Security from fastapi.params import Security
@ -80,7 +82,7 @@ def expect_correct_amount_of_dependency_activations(
) )
@pytest.mark.parametrize("is_websocket", [True, False], ids=["Endpoint", "Websocket"]) @pytest.mark.parametrize("is_websocket", [True, False], ids=["Websocket", "Endpoint"])
@pytest.mark.parametrize("use_cache", [True, False]) @pytest.mark.parametrize("use_cache", [True, False])
@pytest.mark.parametrize("dependency_style", list(DependencyStyle)) @pytest.mark.parametrize("dependency_style", list(DependencyStyle))
@pytest.mark.parametrize("routing_style", ["app_endpoint", "router_endpoint"]) @pytest.mark.parametrize("routing_style", ["app_endpoint", "router_endpoint"])
@ -128,7 +130,7 @@ def test_endpoint_dependencies(
) )
@pytest.mark.parametrize("is_websocket", [True, False], ids=["Endpoint", "Websocket"]) @pytest.mark.parametrize("is_websocket", [True, False], ids=["Websocket", "Endpoint"])
@pytest.mark.parametrize("dependency_duplication", [1, 2]) @pytest.mark.parametrize("dependency_duplication", [1, 2])
@pytest.mark.parametrize("use_cache", [True, False]) @pytest.mark.parametrize("use_cache", [True, False])
@pytest.mark.parametrize("dependency_style", list(DependencyStyle)) @pytest.mark.parametrize("dependency_style", list(DependencyStyle))
@ -179,7 +181,7 @@ def test_router_dependencies(
) )
@pytest.mark.parametrize("is_websocket", [True, False], ids=["Endpoint", "Websocket"]) @pytest.mark.parametrize("is_websocket", [True, False], ids=["Websocket", "Endpoint"])
@pytest.mark.parametrize("use_cache", [True, False]) @pytest.mark.parametrize("use_cache", [True, False])
@pytest.mark.parametrize("dependency_style", list(DependencyStyle)) @pytest.mark.parametrize("dependency_style", list(DependencyStyle))
@pytest.mark.parametrize("routing_style", ["app", "router"]) @pytest.mark.parametrize("routing_style", ["app", "router"])
@ -261,7 +263,7 @@ def test_dependency_cache_in_same_dependency(
) )
@pytest.mark.parametrize("is_websocket", [True, False], ids=["Endpoint", "Websocket"]) @pytest.mark.parametrize("is_websocket", [True, False], ids=["Websocket", "Endpoint"])
@pytest.mark.parametrize("use_cache", [True, False]) @pytest.mark.parametrize("use_cache", [True, False])
@pytest.mark.parametrize("dependency_style", list(DependencyStyle)) @pytest.mark.parametrize("dependency_style", list(DependencyStyle))
@pytest.mark.parametrize("routing_style", ["app", "router"]) @pytest.mark.parametrize("routing_style", ["app", "router"])
@ -330,7 +332,7 @@ def test_dependency_cache_in_same_endpoint(
) )
@pytest.mark.parametrize("is_websocket", [True, False], ids=["Endpoint", "Websocket"]) @pytest.mark.parametrize("is_websocket", [True, False], ids=["Websocket", "Endpoint"])
@pytest.mark.parametrize("use_cache", [True, False]) @pytest.mark.parametrize("use_cache", [True, False])
@pytest.mark.parametrize("dependency_style", list(DependencyStyle)) @pytest.mark.parametrize("dependency_style", list(DependencyStyle))
@pytest.mark.parametrize("routing_style", ["app", "router"]) @pytest.mark.parametrize("routing_style", ["app", "router"])
@ -412,7 +414,7 @@ def test_dependency_cache_in_different_endpoints(
) )
@pytest.mark.parametrize("is_websocket", [True, False], ids=["Endpoint", "Websocket"]) @pytest.mark.parametrize("is_websocket", [True, False], ids=["Websocket", "Endpoint"])
@pytest.mark.parametrize("dependency_style", list(DependencyStyle)) @pytest.mark.parametrize("dependency_style", list(DependencyStyle))
@pytest.mark.parametrize("routing_style", ["app", "router"]) @pytest.mark.parametrize("routing_style", ["app", "router"])
def test_no_cached_dependency( def test_no_cached_dependency(
@ -459,7 +461,7 @@ def test_no_cached_dependency(
) )
@pytest.mark.parametrize("is_websocket", [True, False], ids=["Endpoint", "Websocket"]) @pytest.mark.parametrize("is_websocket", [True, False], ids=["Websocket", "Endpoint"])
@pytest.mark.parametrize( @pytest.mark.parametrize(
"annotation", "annotation",
[ [
@ -472,6 +474,8 @@ def test_no_cached_dependency(
Annotated[str, Form()], Annotated[str, Form()],
Annotated[str, File()], Annotated[str, File()],
BackgroundTasks, BackgroundTasks,
Request,
WebSocket,
], ],
) )
def test_override_lifespan_scoped_dependency_cannot_use_endpoint_scoped_parameters( def test_override_lifespan_scoped_dependency_cannot_use_endpoint_scoped_parameters(
@ -500,7 +504,7 @@ def test_override_lifespan_scoped_dependency_cannot_use_endpoint_scoped_paramete
pass pass
@pytest.mark.parametrize("is_websocket", [True, False], ids=["Endpoint", "Websocket"]) @pytest.mark.parametrize("is_websocket", [True, False], ids=["Websocket", "Endpoint"])
@pytest.mark.parametrize("dependency_style", list(DependencyStyle)) @pytest.mark.parametrize("dependency_style", list(DependencyStyle))
def test_non_override_lifespan_scoped_dependency_can_use_overridden_lifespan_scoped_dependencies( def test_non_override_lifespan_scoped_dependency_can_use_overridden_lifespan_scoped_dependencies(
dependency_style: DependencyStyle, is_websocket dependency_style: DependencyStyle, is_websocket
@ -541,7 +545,7 @@ def test_non_override_lifespan_scoped_dependency_can_use_overridden_lifespan_sco
) )
@pytest.mark.parametrize("is_websocket", [True, False], ids=["Endpoint", "Websocket"]) @pytest.mark.parametrize("is_websocket", [True, False], ids=["Websocket", "Endpoint"])
@pytest.mark.parametrize("depends_class", [Depends, Security]) @pytest.mark.parametrize("depends_class", [Depends, Security])
def test_override_lifespan_scoped_dependency_cannot_use_endpoint_scoped_dependencies( def test_override_lifespan_scoped_dependency_cannot_use_endpoint_scoped_dependencies(
depends_class, is_websocket depends_class, is_websocket
@ -575,7 +579,7 @@ def test_override_lifespan_scoped_dependency_cannot_use_endpoint_scoped_dependen
pass pass
@pytest.mark.parametrize("is_websocket", [True, False], ids=["Endpoint", "Websocket"]) @pytest.mark.parametrize("is_websocket", [True, False], ids=["Websocket", "Endpoint"])
@pytest.mark.parametrize("use_cache", [True, False]) @pytest.mark.parametrize("use_cache", [True, False])
@pytest.mark.parametrize("dependency_style", list(DependencyStyle)) @pytest.mark.parametrize("dependency_style", list(DependencyStyle))
@pytest.mark.parametrize("routing_style", ["app_endpoint", "router_endpoint"]) @pytest.mark.parametrize("routing_style", ["app_endpoint", "router_endpoint"])

45
tests/test_lifespan_scoped_dependencies/test_endpoint_usage.py

@ -1,5 +1,6 @@
import warnings import warnings
from contextlib import asynccontextmanager from contextlib import asynccontextmanager
from time import sleep
from typing import Any, AsyncGenerator, Dict, List, Tuple from typing import Any, AsyncGenerator, Dict, List, Tuple
import pytest import pytest
@ -15,6 +16,8 @@ from fastapi import (
Header, Header,
Path, Path,
Query, Query,
Request,
WebSocket,
) )
from fastapi.exceptions import ( from fastapi.exceptions import (
DependencyScopeConflict, DependencyScopeConflict,
@ -70,7 +73,7 @@ def expect_correct_amount_of_dependency_activations(
assert dependency_factory.deactivation_times == expected_activation_times assert dependency_factory.deactivation_times == expected_activation_times
@pytest.mark.parametrize("is_websocket", [True, False], ids=["Endpoint", "Websocket"]) @pytest.mark.parametrize("is_websocket", [True, False], ids=["Websocket", "Endpoint"])
@pytest.mark.parametrize( @pytest.mark.parametrize(
"use_cache", [True, False], ids=["With Cache", "Without Cache"] "use_cache", [True, False], ids=["With Cache", "Without Cache"]
) )
@ -118,7 +121,7 @@ def test_endpoint_dependencies(
) )
@pytest.mark.parametrize("is_websocket", [True, False], ids=["Endpoint", "Websocket"]) @pytest.mark.parametrize("is_websocket", [True, False], ids=["Websocket", "Endpoint"])
@pytest.mark.parametrize("dependency_duplication", [1, 2]) @pytest.mark.parametrize("dependency_duplication", [1, 2])
@pytest.mark.parametrize("use_cache", [True, False]) @pytest.mark.parametrize("use_cache", [True, False])
@pytest.mark.parametrize("dependency_style", list(DependencyStyle)) @pytest.mark.parametrize("dependency_style", list(DependencyStyle))
@ -163,7 +166,7 @@ def test_router_dependencies(
) )
@pytest.mark.parametrize("is_websocket", [True, False], ids=["Endpoint", "Websocket"]) @pytest.mark.parametrize("is_websocket", [True, False], ids=["Websocket", "Endpoint"])
@pytest.mark.parametrize("use_cache", [True, False]) @pytest.mark.parametrize("use_cache", [True, False])
@pytest.mark.parametrize("dependency_style", list(DependencyStyle)) @pytest.mark.parametrize("dependency_style", list(DependencyStyle))
@pytest.mark.parametrize("routing_style", ["app", "router"]) @pytest.mark.parametrize("routing_style", ["app", "router"])
@ -238,7 +241,7 @@ def test_dependency_cache_in_same_dependency(
) )
@pytest.mark.parametrize("is_websocket", [True, False], ids=["Endpoint", "Websocket"]) @pytest.mark.parametrize("is_websocket", [True, False], ids=["Websocket", "Endpoint"])
@pytest.mark.parametrize("use_cache", [True, False]) @pytest.mark.parametrize("use_cache", [True, False])
@pytest.mark.parametrize("dependency_style", list(DependencyStyle)) @pytest.mark.parametrize("dependency_style", list(DependencyStyle))
@pytest.mark.parametrize("routing_style", ["app", "router"]) @pytest.mark.parametrize("routing_style", ["app", "router"])
@ -300,7 +303,7 @@ def test_dependency_cache_in_same_endpoint(
) )
@pytest.mark.parametrize("is_websocket", [True, False], ids=["Endpoint", "Websocket"]) @pytest.mark.parametrize("is_websocket", [True, False], ids=["Websocket", "Endpoint"])
@pytest.mark.parametrize("use_cache", [True, False]) @pytest.mark.parametrize("use_cache", [True, False])
@pytest.mark.parametrize("dependency_style", list(DependencyStyle)) @pytest.mark.parametrize("dependency_style", list(DependencyStyle))
@pytest.mark.parametrize("routing_style", ["app", "router"]) @pytest.mark.parametrize("routing_style", ["app", "router"])
@ -375,7 +378,7 @@ def test_dependency_cache_in_different_endpoints(
) )
@pytest.mark.parametrize("is_websocket", [True, False], ids=["Endpoint", "Websocket"]) @pytest.mark.parametrize("is_websocket", [True, False], ids=["Websocket", "Endpoint"])
@pytest.mark.parametrize("dependency_style", list(DependencyStyle)) @pytest.mark.parametrize("dependency_style", list(DependencyStyle))
@pytest.mark.parametrize("routing_style", ["app", "router"]) @pytest.mark.parametrize("routing_style", ["app", "router"])
def test_no_cached_dependency( def test_no_cached_dependency(
@ -419,7 +422,7 @@ def test_no_cached_dependency(
) )
@pytest.mark.parametrize("is_websocket", [True, False], ids=["Endpoint", "Websocket"]) @pytest.mark.parametrize("is_websocket", [True, False], ids=["Websocket", "Endpoint"])
@pytest.mark.parametrize( @pytest.mark.parametrize(
"annotation", "annotation",
[ [
@ -432,6 +435,8 @@ def test_no_cached_dependency(
Annotated[str, Form()], Annotated[str, Form()],
Annotated[str, File()], Annotated[str, File()],
BackgroundTasks, BackgroundTasks,
Request,
WebSocket
], ],
) )
def test_lifespan_scoped_dependency_cannot_use_endpoint_scoped_parameters( def test_lifespan_scoped_dependency_cannot_use_endpoint_scoped_parameters(
@ -453,7 +458,7 @@ def test_lifespan_scoped_dependency_cannot_use_endpoint_scoped_parameters(
) )
@pytest.mark.parametrize("is_websocket", [True, False], ids=["Endpoint", "Websocket"]) @pytest.mark.parametrize("is_websocket", [True, False], ids=["Websocket", "Endpoint"])
@pytest.mark.parametrize("dependency_style", list(DependencyStyle)) @pytest.mark.parametrize("dependency_style", list(DependencyStyle))
def test_lifespan_scoped_dependency_can_use_other_lifespan_scoped_dependencies( def test_lifespan_scoped_dependency_can_use_other_lifespan_scoped_dependencies(
dependency_style: DependencyStyle, is_websocket dependency_style: DependencyStyle, is_websocket
@ -487,7 +492,7 @@ def test_lifespan_scoped_dependency_can_use_other_lifespan_scoped_dependencies(
) )
@pytest.mark.parametrize("is_websocket", [True, False], ids=["Endpoint", "Websocket"]) @pytest.mark.parametrize("is_websocket", [True, False], ids=["Websocket", "Endpoint"])
@pytest.mark.parametrize( @pytest.mark.parametrize(
["dependency_style", "supports_teardown"], ["dependency_style", "supports_teardown"],
[ [
@ -530,6 +535,10 @@ def test_the_same_dependency_can_work_in_different_scopes(
assert get_response(client, "/test") == [2, 1] assert get_response(client, "/test") == [2, 1]
assert dependency_factory.activation_times == 2 assert dependency_factory.activation_times == 2
if supports_teardown: if supports_teardown:
if is_websocket:
# Websockets teardown might take some time after the test client
# has disconnected
sleep(0.1)
assert dependency_factory.deactivation_times == 1 assert dependency_factory.deactivation_times == 1
else: else:
assert dependency_factory.deactivation_times == 0 assert dependency_factory.deactivation_times == 0
@ -537,6 +546,10 @@ def test_the_same_dependency_can_work_in_different_scopes(
assert get_response(client, "/test") == [3, 1] assert get_response(client, "/test") == [3, 1]
assert dependency_factory.activation_times == 3 assert dependency_factory.activation_times == 3
if supports_teardown: if supports_teardown:
if is_websocket:
# Websockets teardown might take some time after the test client
# has disconnected
sleep(0.1)
assert dependency_factory.deactivation_times == 2 assert dependency_factory.deactivation_times == 2
else: else:
assert dependency_factory.deactivation_times == 0 assert dependency_factory.deactivation_times == 0
@ -551,7 +564,7 @@ def test_the_same_dependency_can_work_in_different_scopes(
@pytest.mark.parametrize( @pytest.mark.parametrize(
"lifespan_style", ["lifespan_generator", "events_decorator", "events_constructor"] "lifespan_style", ["lifespan_generator", "events_decorator", "events_constructor"]
) )
@pytest.mark.parametrize("is_websocket", [True, False], ids=["Endpoint", "Websocket"]) @pytest.mark.parametrize("is_websocket", [True, False], ids=["Websocket", "Endpoint"])
@pytest.mark.parametrize("dependency_style", list(DependencyStyle)) @pytest.mark.parametrize("dependency_style", list(DependencyStyle))
def test_lifespan_scoped_dependency_can_be_used_alongside_custom_lifespans( def test_lifespan_scoped_dependency_can_be_used_alongside_custom_lifespans(
dependency_style: DependencyStyle, dependency_style: DependencyStyle,
@ -622,7 +635,7 @@ def test_lifespan_scoped_dependency_can_be_used_alongside_custom_lifespans(
assert lifespan_started and lifespan_ended assert lifespan_started and lifespan_ended
@pytest.mark.parametrize("is_websocket", [True, False], ids=["Endpoint", "Websocket"]) @pytest.mark.parametrize("is_websocket", [True, False], ids=["Websocket", "Endpoint"])
@pytest.mark.parametrize("depends_class", [Depends, Security]) @pytest.mark.parametrize("depends_class", [Depends, Security])
def test_lifespan_scoped_dependency_cannot_use_endpoint_scoped_dependencies( def test_lifespan_scoped_dependency_cannot_use_endpoint_scoped_dependencies(
depends_class, is_websocket depends_class, is_websocket
@ -648,7 +661,7 @@ def test_lifespan_scoped_dependency_cannot_use_endpoint_scoped_dependencies(
) )
@pytest.mark.parametrize("is_websocket", [True, False], ids=["Endpoint", "Websocket"]) @pytest.mark.parametrize("is_websocket", [True, False], ids=["Websocket", "Endpoint"])
@pytest.mark.parametrize("use_cache", [True, False]) @pytest.mark.parametrize("use_cache", [True, False])
@pytest.mark.parametrize("dependency_style", list(DependencyStyle)) @pytest.mark.parametrize("dependency_style", list(DependencyStyle))
@pytest.mark.parametrize("routing_style", ["app_endpoint", "router_endpoint"]) @pytest.mark.parametrize("routing_style", ["app_endpoint", "router_endpoint"])
@ -683,7 +696,7 @@ def test_dependencies_must_provide_correct_dependency_scope(
) )
@pytest.mark.parametrize("is_websocket", [True, False], ids=["Endpoint", "Websocket"]) @pytest.mark.parametrize("is_websocket", [True, False], ids=["Websocket", "Endpoint"])
@pytest.mark.parametrize("use_cache", [True, False]) @pytest.mark.parametrize("use_cache", [True, False])
@pytest.mark.parametrize("dependency_style", list(DependencyStyle)) @pytest.mark.parametrize("dependency_style", list(DependencyStyle))
@pytest.mark.parametrize("routing_style", ["app_endpoint", "router_endpoint"]) @pytest.mark.parametrize("routing_style", ["app_endpoint", "router_endpoint"])
@ -717,7 +730,7 @@ def test_endpoints_report_incorrect_dependency_scope(
) )
@pytest.mark.parametrize("is_websocket", [True, False], ids=["Endpoint", "Websocket"]) @pytest.mark.parametrize("is_websocket", [True, False], ids=["Websocket", "Endpoint"])
@pytest.mark.parametrize("use_cache", [True, False]) @pytest.mark.parametrize("use_cache", [True, False])
@pytest.mark.parametrize("dependency_style", list(DependencyStyle)) @pytest.mark.parametrize("dependency_style", list(DependencyStyle))
@pytest.mark.parametrize("routing_style", ["app_endpoint", "router_endpoint"]) @pytest.mark.parametrize("routing_style", ["app_endpoint", "router_endpoint"])
@ -767,7 +780,7 @@ def test_endpoints_report_uninitialized_dependency(
) )
@pytest.mark.parametrize("is_websocket", [True, False], ids=["Endpoint", "Websocket"]) @pytest.mark.parametrize("is_websocket", [True, False], ids=["Websocket", "Endpoint"])
@pytest.mark.parametrize("use_cache", [True, False]) @pytest.mark.parametrize("use_cache", [True, False])
@pytest.mark.parametrize("dependency_style", list(DependencyStyle)) @pytest.mark.parametrize("dependency_style", list(DependencyStyle))
@pytest.mark.parametrize("routing_style", ["app_endpoint", "router_endpoint"]) @pytest.mark.parametrize("routing_style", ["app_endpoint", "router_endpoint"])
@ -815,7 +828,7 @@ def test_endpoints_report_uninitialized_internal_lifespan(
client.app_state["__fastapi__"] = internal_state client.app_state["__fastapi__"] = internal_state
@pytest.mark.parametrize("is_websocket", [True, False], ids=["Endpoint", "Websocket"]) @pytest.mark.parametrize("is_websocket", [True, False], ids=["Websocket", "Endpoint"])
@pytest.mark.parametrize("use_cache", [True, False]) @pytest.mark.parametrize("use_cache", [True, False])
@pytest.mark.parametrize("dependency_style", list(DependencyStyle)) @pytest.mark.parametrize("dependency_style", list(DependencyStyle))
@pytest.mark.parametrize("routing_style", ["app_endpoint", "router_endpoint"]) @pytest.mark.parametrize("routing_style", ["app_endpoint", "router_endpoint"])

4
tests/test_lifespan_scoped_dependencies/testing_utilities.py

@ -1,3 +1,4 @@
import threading
from enum import Enum from enum import Enum
from typing import Any, AsyncGenerator, Generator, List, TypeVar, Union from typing import Any, AsyncGenerator, Generator, List, TypeVar, Union
@ -33,6 +34,7 @@ class DependencyFactory:
self.dependency_style = dependency_style self.dependency_style = dependency_style
self._should_error = should_error self._should_error = should_error
self._value_offset = value_offset self._value_offset = value_offset
self._event = threading.Event()
def get_dependency(self): def get_dependency(self):
if self.dependency_style == DependencyStyle.SYNC_FUNCTION: if self.dependency_style == DependencyStyle.SYNC_FUNCTION:
@ -56,6 +58,7 @@ class DependencyFactory:
yield self.activation_times + self._value_offset yield self.activation_times + self._value_offset
self.deactivation_times += 1 self.deactivation_times += 1
self._event.set()
def _synchronous_generator_dependency(self) -> Generator[T, None, None]: def _synchronous_generator_dependency(self) -> Generator[T, None, None]:
self.activation_times += 1 self.activation_times += 1
@ -64,6 +67,7 @@ class DependencyFactory:
yield self.activation_times + self._value_offset yield self.activation_times + self._value_offset
self.deactivation_times += 1 self.deactivation_times += 1
self._event.set()
async def _asynchronous_function_dependency(self) -> T: async def _asynchronous_function_dependency(self) -> T:
self.activation_times += 1 self.activation_times += 1

Loading…
Cancel
Save