@@ -11,7 +11,7 @@ public static async Task Empty<TElement>(IAsyncEnumerable<TElement> asyncSequenc
1111 {
1212 if ( await asyncEnumerator . MoveNextAsync ( ) )
1313 {
14- throw new EmptyException ( await asyncSequence . ToListAsync ( ) ) ;
14+ throw EmptyException . ForNonEmptyCollection ( collection : await FormatCollectionStart ( asyncSequence ) ) ;
1515 }
1616 }
1717 finally
@@ -27,7 +27,7 @@ public static async Task NotEmpty<TElement>(IAsyncEnumerable<TElement> asyncSequ
2727 {
2828 if ( ! await asyncEnumerator . MoveNextAsync ( ) )
2929 {
30- throw new NotEmptyException ( ) ;
30+ throw NotEmptyException . ForNonEmptyCollection ( ) ;
3131 }
3232 }
3333 finally
@@ -39,25 +39,7 @@ public static async Task NotEmpty<TElement>(IAsyncEnumerable<TElement> asyncSequ
3939 public static async Task Collection < TElement > ( IAsyncEnumerable < TElement > asyncSequence , params Action < TElement > [ ] elementInspectors )
4040 {
4141 var elements = await asyncSequence . ToListAsync ( ) ;
42- var elementInspectorsLength = elementInspectors . Length ;
43- var elementsLength = elements . Count ;
44-
45- if ( elementInspectorsLength != elementsLength )
46- {
47- throw new CollectionException ( asyncSequence . ToListAsync ( ) , elementInspectorsLength , elementsLength ) ;
48- }
49-
50- foreach ( var ( ( elementInspector , element ) , indexFailurePoint ) in elementInspectors . Zip ( elements ) . WithIndex ( ) )
51- {
52- try
53- {
54- elementInspector ( element ) ;
55- }
56- catch ( Exception ex )
57- {
58- throw new CollectionException ( asyncSequence . ToListAsync ( ) , elementInspectorsLength , elementsLength , indexFailurePoint , ex ) ;
59- }
60- }
42+ Assert . Collection ( elements , elementInspectors ) ;
6143 }
6244
6345 public static async Task < T > Single < T > ( IAsyncEnumerable < T > asyncSequence )
@@ -66,19 +48,36 @@ public static async Task<T> Single<T>(IAsyncEnumerable<T> asyncSequence)
6648
6749 if ( await asyncEnumerator . MoveNextAsync ( ) is false )
6850 {
69- SingleException . Empty ( null ) ;
51+ throw SingleException . Empty ( expected : null , collection : string . Empty ) ;
7052 }
7153
7254 var result = asyncEnumerator . Current ;
7355
7456 if ( await asyncEnumerator . MoveNextAsync ( ) )
7557 {
76- SingleException . MoreThanOne ( await asyncSequence . CountAsync ( ) , null ) ;
58+ var actual = await MaterializeCollectionStart ( asyncSequence ) ;
59+ throw SingleException . MoreThanOne ( expected : null , collection : FormatCollectionStart ( actual ) , count : actual . Count , matchIndices : Array . Empty < int > ( ) ) ;
7760 }
7861
7962 return result ;
8063 }
8164
8265 public static async Task Equal < TElement > ( IAsyncEnumerable < TElement > expectedResult , IAsyncEnumerable < TElement > actual )
8366 => Assert . Equal ( await expectedResult . ToListAsync ( ) , await actual . ToListAsync ( ) ) ;
67+
68+ private static async Task < IReadOnlyCollection < TElement > > MaterializeCollectionStart < TElement > ( IAsyncEnumerable < TElement > asyncSequence )
69+ {
70+ // This should *ideally* be kept in sync with XUnit's `ArgumentFormatter.MAX_ENUMERABLE_LENGTH + 1` (which is private).
71+ const int maxEnumerableLength = 6 ;
72+ return await asyncSequence . Take ( maxEnumerableLength ) . ToListAsync ( ) ;
73+ }
74+
75+ private static async Task < string > FormatCollectionStart < TElement > ( IAsyncEnumerable < TElement > asyncSequence )
76+ => FormatCollectionStart ( await MaterializeCollectionStart ( asyncSequence ) ) ;
77+
78+ private static string FormatCollectionStart < TElement > ( IEnumerable < TElement > sequence )
79+ {
80+ using var tracker = sequence . AsTracker ( ) ;
81+ return tracker . FormatStart ( ) ;
82+ }
8483}
0 commit comments