Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
164 changes: 4 additions & 160 deletions tests/server/request_handlers/test_default_request_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
Loading