@@ -1241,168 +1241,12 @@ def sync_get_event_stream_gen(*args, **kwargs):
12411241 side_effect = sync_get_event_stream_gen
12421242 )
12431243
1244- # Mock current_result property to return appropriate awaitables
1245- # Coroutines that will be returned by successive accesses to current_result
1246- async def current_result_coro1 ():
1247- return event1_task_update
1248-
1249- async def current_result_coro2 ():
1250- return event2_final_task
1251-
1252- # Use unittest.mock.PropertyMock for async property
1253- # We need to patch 'ResultAggregator.current_result' when this instance is used.
1254- # This is complex because ResultAggregator is instantiated inside the handler.
1255- # Easier: If mock_result_aggregator_instance is a MagicMock, we can assign a callable.
1256- # This part is tricky. Let's assume current_result is an async method for easier mocking first.
1257- # If it's truly a property, the mocking is harder with instance mocks.
1258- # Let's adjust the mock_result_aggregator_instance.current_result to be an AsyncMock directly
1259- # This means the code would call `await result_aggregator.current_result()`
1260- # But the actual code is `await result_aggregator.current_result`
1261- # This implies `result_aggregator.current_result` IS an awaitable.
1262- # So, we can mock it with a side_effect that returns awaitables (coroutines).
1263-
1264- # Create simple awaitables (coroutines) for side_effect
1265- async def get_event1 ():
1266- return event1_task_update
1267-
1268- async def get_event2 ():
1269- return event2_final_task
1270-
1271- # Make the current_result attribute of the mock instance itself an awaitable
1272- # This still means current_result is not callable.
1273- # For an async property, the mock needs to have current_result as a non-AsyncMock attribute
1274- # that is itself an awaitable.
1275-
1276- # Let's try to mock the property at the type level for ResultAggregator temporarily
1277- # This is not ideal as it affects all instances.
1278-
1279- # Alternative: Configure the AsyncMock for current_result to return a coroutine
1280- # when it's awaited. This is not directly supported by AsyncMock for property access.
1281-
1282- # Simplest for now: Assume `current_result` attribute of the mocked `ResultAggregator` instance
1283- # can be sequentially awaited if it's a list of awaitables that a test runner can handle.
1284- # This is likely to fail again but will clarify the exact point of await.
1285- # The error "TypeError: object AsyncMock can't be used in 'await' expression" means
1286- # `mock_result_aggregator_instance.current_result` is an AsyncMock, and that's what's awaited.
1287- # This AsyncMock needs to have a __await__ method.
1288-
1289- # Let's make the side_effect of the AsyncMock `current_result` provide the values.
1290- # This assumes that `await mock.property` somehow triggers a call to the mock.
1291- # This is not how AsyncMock works.
1292-
1293- # The code is `await result_aggregator.current_result`.
1294- # `result_aggregator` is an instance of `ResultAggregator`.
1295- # `current_result` is an async property.
1296- # So `result_aggregator.current_result` evaluates to a coroutine.
1297- # We need `mock_result_aggregator_instance.current_result` to be a coroutine,
1298- # or a list of coroutines if accessed multiple times.
1299- # This is best done by mocking the property itself.
1300- # Let's assume it's called twice.
1301-
1302- # We will patch ResultAggregator to be our mock_result_aggregator_instance
1303- # Then, we need to control what its `current_result` property returns.
1304- # We can use a PropertyMock for this, attached to the type of mock_result_aggregator_instance.
1305-
1306- # For this specific test, let's make current_result a simple async def method on the mock instance
1307- # This means we are slightly diverging from the "property" nature just for this mock.
1308- # Mock current_result property to return appropriate awaitables (coroutines) sequentially.
1309- async def get_event1_coro ():
1310- return event1_task_update
1311-
1312- async def get_event2_coro ():
1313- return event2_final_task
1314-
1315- # Configure the 'current_result' property on the type of the mock instance
1316- # This makes accessing `instance.current_result` call the side_effect function,
1317- # which then cycles through our list of coroutines.
1318- # We need a new PropertyMock for each instance, or patch the class.
1319- # Since mock_result_aggregator_instance is already created, we attach to its type.
1320- # This can be tricky. A more direct way is to ensure the instance's attribute `current_result`
1321- # behaves as desired. If `mock_result_aggregator_instance` is a `MagicMock`, its attributes are also mocks.
1322-
1323- # Let's make `current_result` a MagicMock whose side_effect returns the coroutines.
1324- # This means when `result_aggregator.current_result` is accessed, this mock is "called".
1325- # This isn't quite right for a property. A property isn't "called" on access.
1326-
1327- # Correct approach for mocking an async property on an instance mock:
1328- # Set the attribute `current_result` on the instance `mock_result_aggregator_instance`
1329- # to be a `PropertyMock` if we were patching the class.
1330- # Since we have the instance, we can try to replace its `current_result` attribute.
1331- # The instance `mock_result_aggregator_instance` is a `MagicMock`.
1332- # We can make `mock_result_aggregator_instance.current_result` a `PropertyMock`
1333- # that returns a coroutine. For multiple calls, `side_effect` on `PropertyMock` is a list of return_values.
1334-
1335- # Create a PropertyMock that will cycle through coroutines
1336- # This requires Python 3.8+ for PropertyMock to be directly usable with side_effect list for properties.
1337- # For older versions or for clarity with async properties, directly mocking the attribute
1338- # to be a series of awaitables is hard.
1339- # The easiest is to ensure `current_result` is an AsyncMock that returns the values.
1340- # The product code `await result_aggregator.current_result` means `current_result` must be an awaitable.
1341-
1342- # Let's make current_result an AsyncMock whose __call__ returns the sequence.
1343- # Mock current_result as an async property
1344- # Create coroutines that will be the "result" of awaiting the property
1345- async def get_current_result_coro1 ():
1346- return event1_task_update
1347-
1348- async def get_current_result_coro2 ():
1349- return event2_final_task
1350-
1351- # Configure the 'current_result' property on the mock_result_aggregator_instance
1352- # using PropertyMock attached to its type. This makes instance.current_result return
1353- # items from side_effect sequentially on each access.
1354- # Since current_result is an async property, these items should be coroutines.
1355- # We need to ensure that mock_result_aggregator_instance itself is the one patched.
1356- # The patch for ResultAggregator returns this instance.
1357- # So, we configure PropertyMock on the type of this specific mock instance.
1358- # This is slightly unusual; typically PropertyMock is used when patching a class.
1359- # A more straightforward approach for an instance is if its type is already a mock.
1360- # As mock_result_aggregator_instance is a MagicMock, we can configure its 'current_result'
1361- # attribute to be a PropertyMock.
1362-
1363- # Let's directly assign a PropertyMock to the type of the instance for `current_result`
1364- # This ensures that when `instance.current_result` is accessed, the PropertyMock's logic is triggered.
1365- # However, PropertyMock is usually used with `patch.object` or by setting it on the class.
1366- #
1367- # A simpler way for MagicMock instance:
1368- # `mock_result_aggregator_instance.current_result` is already a MagicMock (or AsyncMock if spec'd).
1369- # We need to make it return a coroutine upon access.
1370- # The most direct way to mock an async property on a MagicMock instance
1371- # such that it returns a sequence of awaitables:
1372- async def side_effect_current_result ():
1373- yield event1_task_update
1374- yield event2_final_task
1375-
1376- # Create an async generator from the side effect
1377- current_result_gen = side_effect_current_result ()
1378-
1379- # Make current_result return the next item from this generator (wrapped in a coroutine)
1380- # each time it's accessed.
1381- async def get_next_current_result ():
1382- try :
1383- return await current_result_gen .__anext__ ()
1384- except StopAsyncIteration :
1385- # Handle case where it's awaited more times than values provided
1386- return None # Or raise an error
1387-
1388- # Since current_result is a property, accessing it should return a coroutine.
1389- # We can achieve this by making mock_result_aggregator_instance.current_result
1390- # a MagicMock whose side_effect returns these coroutines.
1391- # This is still tricky because it's a property access.
1392-
1393- # Let's use the PropertyMock on the class being mocked via the patch.
1394- # Setup for consume_and_emit
1395- def sync_get_event_stream_gen_for_prop_test (* args , ** kwargs ):
1396- return event_stream_gen ()
1397-
1398- mock_result_aggregator_instance .consume_and_emit = MagicMock (
1399- side_effect = sync_get_event_stream_gen_for_prop_test
1400- )
1244+ # Mock current_result as an async property returning events sequentially.
1245+ async def to_coro (val ):
1246+ return val
14011247
1402- # Configure current_result on the type of the mock_result_aggregator_instance
1403- # This makes it behave like a property that returns items from side_effect on access.
14041248 type(mock_result_aggregator_instance ).current_result = PropertyMock (
1405- side_effect = [get_current_result_coro1 ( ), get_current_result_coro2 ( )]
1249+ side_effect = [to_coro ( event1_task_update ), to_coro ( event2_final_task )]
14061250 )
14071251
14081252 context = create_server_call_context ()
0 commit comments