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