diff --git a/tests/server/request_handlers/test_default_request_handler.py b/tests/server/request_handlers/test_default_request_handler.py index e25957198..1d4a90515 100644 --- a/tests/server/request_handlers/test_default_request_handler.py +++ b/tests/server/request_handlers/test_default_request_handler.py @@ -1241,168 +1241,12 @@ def sync_get_event_stream_gen(*args, **kwargs): side_effect=sync_get_event_stream_gen ) - # Mock current_result property to return appropriate awaitables - # Coroutines that will be returned by successive accesses to current_result - async def current_result_coro1(): - return event1_task_update - - async def current_result_coro2(): - return event2_final_task - - # Use unittest.mock.PropertyMock for async property - # We need to patch 'ResultAggregator.current_result' when this instance is used. - # This is complex because ResultAggregator is instantiated inside the handler. - # Easier: If mock_result_aggregator_instance is a MagicMock, we can assign a callable. - # This part is tricky. Let's assume current_result is an async method for easier mocking first. - # If it's truly a property, the mocking is harder with instance mocks. - # Let's adjust the mock_result_aggregator_instance.current_result to be an AsyncMock directly - # This means the code would call `await result_aggregator.current_result()` - # But the actual code is `await result_aggregator.current_result` - # This implies `result_aggregator.current_result` IS an awaitable. - # So, we can mock it with a side_effect that returns awaitables (coroutines). - - # Create simple awaitables (coroutines) for side_effect - async def get_event1(): - return event1_task_update - - async def get_event2(): - return event2_final_task - - # Make the current_result attribute of the mock instance itself an awaitable - # This still means current_result is not callable. - # For an async property, the mock needs to have current_result as a non-AsyncMock attribute - # that is itself an awaitable. - - # Let's try to mock the property at the type level for ResultAggregator temporarily - # This is not ideal as it affects all instances. - - # Alternative: Configure the AsyncMock for current_result to return a coroutine - # when it's awaited. This is not directly supported by AsyncMock for property access. - - # Simplest for now: Assume `current_result` attribute of the mocked `ResultAggregator` instance - # can be sequentially awaited if it's a list of awaitables that a test runner can handle. - # This is likely to fail again but will clarify the exact point of await. - # The error "TypeError: object AsyncMock can't be used in 'await' expression" means - # `mock_result_aggregator_instance.current_result` is an AsyncMock, and that's what's awaited. - # This AsyncMock needs to have a __await__ method. - - # Let's make the side_effect of the AsyncMock `current_result` provide the values. - # This assumes that `await mock.property` somehow triggers a call to the mock. - # This is not how AsyncMock works. - - # The code is `await result_aggregator.current_result`. - # `result_aggregator` is an instance of `ResultAggregator`. - # `current_result` is an async property. - # So `result_aggregator.current_result` evaluates to a coroutine. - # We need `mock_result_aggregator_instance.current_result` to be a coroutine, - # or a list of coroutines if accessed multiple times. - # This is best done by mocking the property itself. - # Let's assume it's called twice. - - # We will patch ResultAggregator to be our mock_result_aggregator_instance - # Then, we need to control what its `current_result` property returns. - # We can use a PropertyMock for this, attached to the type of mock_result_aggregator_instance. - - # For this specific test, let's make current_result a simple async def method on the mock instance - # This means we are slightly diverging from the "property" nature just for this mock. - # Mock current_result property to return appropriate awaitables (coroutines) sequentially. - async def get_event1_coro(): - return event1_task_update - - async def get_event2_coro(): - return event2_final_task - - # Configure the 'current_result' property on the type of the mock instance - # This makes accessing `instance.current_result` call the side_effect function, - # which then cycles through our list of coroutines. - # We need a new PropertyMock for each instance, or patch the class. - # Since mock_result_aggregator_instance is already created, we attach to its type. - # This can be tricky. A more direct way is to ensure the instance's attribute `current_result` - # behaves as desired. If `mock_result_aggregator_instance` is a `MagicMock`, its attributes are also mocks. - - # Let's make `current_result` a MagicMock whose side_effect returns the coroutines. - # This means when `result_aggregator.current_result` is accessed, this mock is "called". - # This isn't quite right for a property. A property isn't "called" on access. - - # Correct approach for mocking an async property on an instance mock: - # Set the attribute `current_result` on the instance `mock_result_aggregator_instance` - # to be a `PropertyMock` if we were patching the class. - # Since we have the instance, we can try to replace its `current_result` attribute. - # The instance `mock_result_aggregator_instance` is a `MagicMock`. - # We can make `mock_result_aggregator_instance.current_result` a `PropertyMock` - # that returns a coroutine. For multiple calls, `side_effect` on `PropertyMock` is a list of return_values. - - # Create a PropertyMock that will cycle through coroutines - # This requires Python 3.8+ for PropertyMock to be directly usable with side_effect list for properties. - # For older versions or for clarity with async properties, directly mocking the attribute - # to be a series of awaitables is hard. - # The easiest is to ensure `current_result` is an AsyncMock that returns the values. - # The product code `await result_aggregator.current_result` means `current_result` must be an awaitable. - - # Let's make current_result an AsyncMock whose __call__ returns the sequence. - # Mock current_result as an async property - # Create coroutines that will be the "result" of awaiting the property - async def get_current_result_coro1(): - return event1_task_update - - async def get_current_result_coro2(): - return event2_final_task - - # Configure the 'current_result' property on the mock_result_aggregator_instance - # using PropertyMock attached to its type. This makes instance.current_result return - # items from side_effect sequentially on each access. - # Since current_result is an async property, these items should be coroutines. - # We need to ensure that mock_result_aggregator_instance itself is the one patched. - # The patch for ResultAggregator returns this instance. - # So, we configure PropertyMock on the type of this specific mock instance. - # This is slightly unusual; typically PropertyMock is used when patching a class. - # A more straightforward approach for an instance is if its type is already a mock. - # As mock_result_aggregator_instance is a MagicMock, we can configure its 'current_result' - # attribute to be a PropertyMock. - - # Let's directly assign a PropertyMock to the type of the instance for `current_result` - # This ensures that when `instance.current_result` is accessed, the PropertyMock's logic is triggered. - # However, PropertyMock is usually used with `patch.object` or by setting it on the class. - # - # A simpler way for MagicMock instance: - # `mock_result_aggregator_instance.current_result` is already a MagicMock (or AsyncMock if spec'd). - # We need to make it return a coroutine upon access. - # The most direct way to mock an async property on a MagicMock instance - # such that it returns a sequence of awaitables: - async def side_effect_current_result(): - yield event1_task_update - yield event2_final_task - - # Create an async generator from the side effect - current_result_gen = side_effect_current_result() - - # Make current_result return the next item from this generator (wrapped in a coroutine) - # each time it's accessed. - async def get_next_current_result(): - try: - return await current_result_gen.__anext__() - except StopAsyncIteration: - # Handle case where it's awaited more times than values provided - return None # Or raise an error - - # Since current_result is a property, accessing it should return a coroutine. - # We can achieve this by making mock_result_aggregator_instance.current_result - # a MagicMock whose side_effect returns these coroutines. - # This is still tricky because it's a property access. - - # Let's use the PropertyMock on the class being mocked via the patch. - # Setup for consume_and_emit - def sync_get_event_stream_gen_for_prop_test(*args, **kwargs): - return event_stream_gen() - - mock_result_aggregator_instance.consume_and_emit = MagicMock( - side_effect=sync_get_event_stream_gen_for_prop_test - ) + # Mock current_result as an async property returning events sequentially. + async def to_coro(val): + return val - # Configure current_result on the type of the mock_result_aggregator_instance - # This makes it behave like a property that returns items from side_effect on access. type(mock_result_aggregator_instance).current_result = PropertyMock( - side_effect=[get_current_result_coro1(), get_current_result_coro2()] + side_effect=[to_coro(event1_task_update), to_coro(event2_final_task)] ) context = create_server_call_context()