@@ -459,45 +459,56 @@ await _objectLifecycleService.RegisterObjectAsync(
459459 const string skipReason = "Data source returned no data" ;
460460
461461 Type [ ] resolvedClassGenericArgs ;
462+ Exception ? genericResolutionException = null ;
462463 try
463464 {
464465 resolvedClassGenericArgs = metadata . TestClassType . IsGenericTypeDefinition
465466 ? TryInferClassGenericsFromDataSources ( metadata )
466467 : Type . EmptyTypes ;
467468 }
468- catch
469+ catch ( Exception ex )
469470 {
470471 resolvedClassGenericArgs = Type . EmptyTypes ;
472+ genericResolutionException = ex ;
471473 }
472474
473- var testData = new TestData
475+ // If generic type inference failed, create a failed test instead of skipped
476+ if ( genericResolutionException != null )
474477 {
475- TestClassInstanceFactory = ( ) => Task . FromResult < object > ( SkippedTestInstance . Instance ) ,
476- ClassDataSourceAttributeIndex = classDataAttributeIndex ,
477- ClassDataLoopIndex = classDataLoopIndex ,
478- ClassData = classData ,
479- MethodDataSourceAttributeIndex = methodDataAttributeIndex ,
480- MethodDataLoopIndex = 1 , // Use 1 since we're creating a single skipped test
481- MethodData = [ ] ,
482- RepeatIndex = 0 ,
483- InheritanceDepth = metadata . InheritanceDepth ,
484- ResolvedClassGenericArguments = resolvedClassGenericArgs ,
485- ResolvedMethodGenericArguments = Type . EmptyTypes
486- } ;
487-
488- var testSpecificContext = new TestBuilderContext
478+ var failedTest = await CreateFailedTestForDataGenerationError ( metadata , genericResolutionException ) ;
479+ tests . Add ( failedTest ) ;
480+ }
481+ else
489482 {
490- TestMetadata = metadata . MethodMetadata ,
491- Events = new TestContextEvents ( ) ,
492- StateBag = new ConcurrentDictionary < string , object ? > ( ) ,
493- ClassConstructor = testBuilderContext . ClassConstructor ,
494- DataSourceAttribute = methodDataSource ,
495- InitializedAttributes = attributes
496- } ;
497-
498- var test = await BuildTestAsync ( metadata , testData , testSpecificContext ) ;
499- test . Context . SkipReason = skipReason ;
500- tests . Add ( test ) ;
483+ var testData = new TestData
484+ {
485+ TestClassInstanceFactory = ( ) => Task . FromResult < object > ( SkippedTestInstance . Instance ) ,
486+ ClassDataSourceAttributeIndex = classDataAttributeIndex ,
487+ ClassDataLoopIndex = classDataLoopIndex ,
488+ ClassData = classData ,
489+ MethodDataSourceAttributeIndex = methodDataAttributeIndex ,
490+ MethodDataLoopIndex = 1 , // Use 1 since we're creating a single skipped test
491+ MethodData = [ ] ,
492+ RepeatIndex = 0 ,
493+ InheritanceDepth = metadata . InheritanceDepth ,
494+ ResolvedClassGenericArguments = resolvedClassGenericArgs ,
495+ ResolvedMethodGenericArguments = Type . EmptyTypes
496+ } ;
497+
498+ var testSpecificContext = new TestBuilderContext
499+ {
500+ TestMetadata = metadata . MethodMetadata ,
501+ Events = new TestContextEvents ( ) ,
502+ StateBag = new ConcurrentDictionary < string , object ? > ( ) ,
503+ ClassConstructor = testBuilderContext . ClassConstructor ,
504+ DataSourceAttribute = methodDataSource ,
505+ InitializedAttributes = attributes
506+ } ;
507+
508+ var test = await BuildTestAsync ( metadata , testData , testSpecificContext ) ;
509+ test . Context . SkipReason = skipReason ;
510+ tests . Add ( test ) ;
511+ }
501512 }
502513 }
503514 }
@@ -508,45 +519,56 @@ await _objectLifecycleService.RegisterObjectAsync(
508519 const string skipReason = "Data source returned no data" ;
509520
510521 Type [ ] resolvedClassGenericArgs ;
522+ Exception ? genericResolutionException = null ;
511523 try
512524 {
513525 resolvedClassGenericArgs = metadata . TestClassType . IsGenericTypeDefinition
514526 ? TryInferClassGenericsFromDataSources ( metadata )
515527 : Type . EmptyTypes ;
516528 }
517- catch
529+ catch ( Exception ex )
518530 {
519531 resolvedClassGenericArgs = Type . EmptyTypes ;
532+ genericResolutionException = ex ;
520533 }
521534
522- var testData = new TestData
535+ // If generic type inference failed, create a failed test instead of skipped
536+ if ( genericResolutionException != null )
523537 {
524- TestClassInstanceFactory = ( ) => Task . FromResult < object > ( SkippedTestInstance . Instance ) ,
525- ClassDataSourceAttributeIndex = classDataAttributeIndex ,
526- ClassDataLoopIndex = 1 , // Use 1 since we're creating a single skipped test
527- ClassData = [ ] ,
528- MethodDataSourceAttributeIndex = 0 ,
529- MethodDataLoopIndex = 0 ,
530- MethodData = [ ] ,
531- RepeatIndex = 0 ,
532- InheritanceDepth = metadata . InheritanceDepth ,
533- ResolvedClassGenericArguments = resolvedClassGenericArgs ,
534- ResolvedMethodGenericArguments = Type . EmptyTypes
535- } ;
536-
537- var testSpecificContext = new TestBuilderContext
538+ var failedTest = await CreateFailedTestForDataGenerationError ( metadata , genericResolutionException ) ;
539+ tests . Add ( failedTest ) ;
540+ }
541+ else
538542 {
539- TestMetadata = metadata . MethodMetadata ,
540- Events = new TestContextEvents ( ) ,
541- StateBag = new ConcurrentDictionary < string , object ? > ( ) ,
542- ClassConstructor = testBuilderContext . ClassConstructor ,
543- DataSourceAttribute = classDataSource ,
544- InitializedAttributes = attributes
545- } ;
546-
547- var test = await BuildTestAsync ( metadata , testData , testSpecificContext ) ;
548- test . Context . SkipReason = skipReason ;
549- tests . Add ( test ) ;
543+ var testData = new TestData
544+ {
545+ TestClassInstanceFactory = ( ) => Task . FromResult < object > ( SkippedTestInstance . Instance ) ,
546+ ClassDataSourceAttributeIndex = classDataAttributeIndex ,
547+ ClassDataLoopIndex = 1 , // Use 1 since we're creating a single skipped test
548+ ClassData = [ ] ,
549+ MethodDataSourceAttributeIndex = 0 ,
550+ MethodDataLoopIndex = 0 ,
551+ MethodData = [ ] ,
552+ RepeatIndex = 0 ,
553+ InheritanceDepth = metadata . InheritanceDepth ,
554+ ResolvedClassGenericArguments = resolvedClassGenericArgs ,
555+ ResolvedMethodGenericArguments = Type . EmptyTypes
556+ } ;
557+
558+ var testSpecificContext = new TestBuilderContext
559+ {
560+ TestMetadata = metadata . MethodMetadata ,
561+ Events = new TestContextEvents ( ) ,
562+ StateBag = new ConcurrentDictionary < string , object ? > ( ) ,
563+ ClassConstructor = testBuilderContext . ClassConstructor ,
564+ DataSourceAttribute = classDataSource ,
565+ InitializedAttributes = attributes
566+ } ;
567+
568+ var test = await BuildTestAsync ( metadata , testData , testSpecificContext ) ;
569+ test . Context . SkipReason = skipReason ;
570+ tests . Add ( test ) ;
571+ }
550572 }
551573 }
552574
@@ -1314,6 +1336,26 @@ internal class TestData
13141336 public Type [ ] ResolvedMethodGenericArguments { get ; set ; } = Type . EmptyTypes ;
13151337 }
13161338
1339+ /// <summary>
1340+ /// Result of attempting to create an instance for method data sources.
1341+ /// Captures either success with an instance or failure with the exception.
1342+ /// </summary>
1343+ private readonly struct InstanceCreationResult
1344+ {
1345+ public object ? Instance { get ; }
1346+ public Exception ? Exception { get ; }
1347+ public bool Success => Exception == null ;
1348+
1349+ private InstanceCreationResult ( object ? instance , Exception ? exception )
1350+ {
1351+ Instance = instance ;
1352+ Exception = exception ;
1353+ }
1354+
1355+ public static InstanceCreationResult CreateSuccess ( object ? instance ) => new ( instance , null ) ;
1356+ public static InstanceCreationResult CreateFailure ( Exception exception ) => new ( null , exception ) ;
1357+ }
1358+
13171359#if NET6_0_OR_GREATER
13181360 [ RequiresUnreferencedCode ( "Test building in reflection mode uses generic type resolution which requires unreferenced code" ) ]
13191361#endif
@@ -1403,14 +1445,18 @@ public async IAsyncEnumerable<AbstractExecutableTest> BuildTestsStreamingAsync(
14031445
14041446 if ( needsInstanceForMethodDataSources )
14051447 {
1406- instanceForMethodDataSources = await CreateInstanceForMethodDataSources (
1448+ var instanceResult = await CreateInstanceForMethodDataSources (
14071449 metadata , classDataAttributeIndex , classDataLoopIndex , classData ) ;
14081450
1409- if ( instanceForMethodDataSources == null )
1451+ if ( ! instanceResult . Success )
14101452 {
1411- continue ; // Skip if instance creation failed
1453+ // Yield a failed test instead of silently skipping
1454+ yield return await CreateFailedTestForInstanceDataSourceError ( metadata , instanceResult . Exception ! ) ;
1455+ continue ;
14121456 }
14131457
1458+ instanceForMethodDataSources = instanceResult . Instance ! ;
1459+
14141460 // Initialize property data sources on the early instance so that
14151461 // method data sources can access fully-initialized properties.
14161462 var tempObjectBag = new ConcurrentDictionary < string , object ? > ( ) ;
@@ -1472,7 +1518,7 @@ await _objectLifecycleService.RegisterObjectAsync(
14721518#if NET6_0_OR_GREATER
14731519 [ RequiresUnreferencedCode ( "Generic type resolution for instance creation uses reflection" ) ]
14741520#endif
1475- private Task < object ? > CreateInstanceForMethodDataSources (
1521+ private Task < InstanceCreationResult > CreateInstanceForMethodDataSources (
14761522 TestMetadata metadata , int classDataAttributeIndex , int classDataLoopIndex , object ? [ ] classData )
14771523 {
14781524 try
@@ -1495,22 +1541,22 @@ await _objectLifecycleService.RegisterObjectAsync(
14951541 try
14961542 {
14971543 var resolution = TestGenericTypeResolver . Resolve ( metadata , tempTestData ) ;
1498- return Task . FromResult < object ? > ( metadata . InstanceFactory ( resolution . ResolvedClassGenericArguments , classData ) ) ;
1544+ return Task . FromResult ( InstanceCreationResult . CreateSuccess ( metadata . InstanceFactory ( resolution . ResolvedClassGenericArguments , classData ) ) ) ;
14991545 }
15001546 catch ( GenericTypeResolutionException ) when ( classData . Length == 0 )
15011547 {
15021548 var resolvedTypes = TryInferClassGenericsFromDataSources ( metadata ) ;
1503- return Task . FromResult < object ? > ( metadata . InstanceFactory ( resolvedTypes , classData ) ) ;
1549+ return Task . FromResult ( InstanceCreationResult . CreateSuccess ( metadata . InstanceFactory ( resolvedTypes , classData ) ) ) ;
15041550 }
15051551 }
15061552 else
15071553 {
1508- return Task . FromResult < object ? > ( metadata . InstanceFactory ( [ ] , classData ) ) ;
1554+ return Task . FromResult ( InstanceCreationResult . CreateSuccess ( metadata . InstanceFactory ( [ ] , classData ) ) ) ;
15091555 }
15101556 }
1511- catch
1557+ catch ( Exception ex )
15121558 {
1513- return Task . FromResult < object ? > ( null ) ;
1559+ return Task . FromResult ( InstanceCreationResult . CreateFailure ( ex ) ) ;
15141560 }
15151561 }
15161562
0 commit comments