@@ -1195,6 +1195,101 @@ async Task<int> OrchestratorFunc(TaskOrchestrationContext ctx, int counter)
11951195 Assert . Equal ( EventCount , metadata . ReadOutputAs < int > ( ) ) ;
11961196 }
11971197
1198- // TODO: Test for multiple external events with the same name
1199- // TODO: Test for catching activity exceptions of specific types
1198+ [ Fact ]
1199+ public async Task CatchingActivityExceptionsByType ( )
1200+ {
1201+ TaskName orchestratorName = nameof ( CatchingActivityExceptionsByType ) ;
1202+ TaskName throwInvalidOpActivityName = "ThrowInvalidOp" ;
1203+ TaskName throwArgumentActivityName = "ThrowArgument" ;
1204+ TaskName successActivityName = "Success" ;
1205+
1206+ await using HostTestLifetime server = await this . StartWorkerAsync ( b =>
1207+ {
1208+ b . AddTasks ( tasks => tasks
1209+ . AddOrchestratorFunc ( orchestratorName , async ctx =>
1210+ {
1211+ List < string > results = new ( ) ;
1212+
1213+ // Test 1: Catch InvalidOperationException
1214+ try
1215+ {
1216+ await ctx . CallActivityAsync ( throwInvalidOpActivityName ) ;
1217+ results . Add ( "No exception thrown" ) ;
1218+ }
1219+ catch ( TaskFailedException ex ) when ( ex . FailureDetails ? . IsCausedBy < InvalidOperationException > ( ) == true )
1220+ {
1221+ results . Add ( "Caught InvalidOperationException" ) ;
1222+ }
1223+ catch ( TaskFailedException )
1224+ {
1225+ results . Add ( "Caught wrong exception type" ) ;
1226+ }
1227+
1228+ // Test 2: Catch ArgumentException
1229+ try
1230+ {
1231+ await ctx . CallActivityAsync ( throwArgumentActivityName ) ;
1232+ results . Add ( "No exception thrown" ) ;
1233+ }
1234+ catch ( TaskFailedException ex ) when ( ex . FailureDetails ? . IsCausedBy < ArgumentException > ( ) == true )
1235+ {
1236+ results . Add ( "Caught ArgumentException" ) ;
1237+ }
1238+ catch ( TaskFailedException )
1239+ {
1240+ results . Add ( "Caught wrong exception type" ) ;
1241+ }
1242+
1243+ // Test 3: Successful activity should not throw
1244+ try
1245+ {
1246+ string result = await ctx . CallActivityAsync < string > ( successActivityName ) ;
1247+ results . Add ( result ) ;
1248+ }
1249+ catch ( TaskFailedException )
1250+ {
1251+ results . Add ( "Unexpected exception" ) ;
1252+ }
1253+
1254+ // Test 4: Catch with base Exception type
1255+ try
1256+ {
1257+ await ctx . CallActivityAsync ( throwInvalidOpActivityName ) ;
1258+ results . Add ( "No exception thrown" ) ;
1259+ }
1260+ catch ( TaskFailedException ex ) when ( ex . FailureDetails ? . IsCausedBy < Exception > ( ) == true )
1261+ {
1262+ results . Add ( "Caught base Exception" ) ;
1263+ }
1264+
1265+ return results ;
1266+ } )
1267+ . AddActivityFunc ( throwInvalidOpActivityName , ( TaskActivityContext ctx ) =>
1268+ {
1269+ throw new InvalidOperationException ( "Invalid operation" ) ;
1270+ } )
1271+ . AddActivityFunc ( throwArgumentActivityName , ( TaskActivityContext ctx ) =>
1272+ {
1273+ throw new ArgumentException ( "Invalid argument" ) ;
1274+ } )
1275+ . AddActivityFunc < string > ( successActivityName , ( TaskActivityContext ctx ) =>
1276+ {
1277+ return "Success" ;
1278+ } ) ) ;
1279+ } ) ;
1280+
1281+ string instanceId = await server . Client . ScheduleNewOrchestrationInstanceAsync ( orchestratorName ) ;
1282+ OrchestrationMetadata metadata = await server . Client . WaitForInstanceCompletionAsync (
1283+ instanceId , getInputsAndOutputs : true , this . TimeoutToken ) ;
1284+ Assert . NotNull ( metadata ) ;
1285+ Assert . Equal ( OrchestrationRuntimeStatus . Completed , metadata . RuntimeStatus ) ;
1286+
1287+ List < string > ? results = metadata . ReadOutputAs < List < string > > ( ) ;
1288+ Assert . NotNull ( results ) ;
1289+ Assert . Equal ( 4 , results ! . Count ) ;
1290+ Assert . Equal ( "Caught InvalidOperationException" , results [ 0 ] ) ;
1291+ Assert . Equal ( "Caught ArgumentException" , results [ 1 ] ) ;
1292+ Assert . Equal ( "Success" , results [ 2 ] ) ;
1293+ Assert . Equal ( "Caught base Exception" , results [ 3 ] ) ;
1294+ }
12001295}
0 commit comments