forked from fluentassertions/fluentassertions
-
Notifications
You must be signed in to change notification settings - Fork 0
/
AssertionExtensions.Actions.cs
131 lines (121 loc) · 5.88 KB
/
AssertionExtensions.Actions.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using FluentAssertions.Common;
using FluentAssertions.Specialized;
namespace FluentAssertions
{
public static partial class AssertionExtensions
{
private static readonly AggregateExceptionExtractor extractor = new AggregateExceptionExtractor();
/// <summary>
/// Asserts that the <paramref name="actionAssertions"/> subject throws the exact exception (and not a derived exception type).
/// </summary>
/// <param name="actionAssertions">A reference to the method or property.</param>
/// <typeparam name="TException">
/// The type of the exception it should throw.
/// </typeparam>
/// <param name="because">
/// A formatted phrase explaining why the assertion should be satisfied. If the phrase does not
/// start with the word <i>because</i>, it is prepended to the message.
/// </param>
/// <param name="becauseArgs">
/// Zero or more values to use for filling in any <see cref="string.Format(string,object[])"/> compatible placeholders.
/// </param>
/// <returns>
/// Returns an object that allows asserting additional members of the thrown exception.
/// </returns>
public static ExceptionAssertions<TException> ThrowExactly<TException>(
this ActionAssertions actionAssertions,
string because = "",
params object[] becauseArgs)
where TException : Exception
{
var exceptionAssertions = actionAssertions.Throw<TException>(because, becauseArgs);
exceptionAssertions.Which.GetType().Should().Be<TException>(because, becauseArgs);
return exceptionAssertions;
}
/// <summary>
/// Asserts that the <paramref name="asyncActionAssertions"/> subject throws the exact exception (and not a derived exception type).
/// </summary>
/// <param name="asyncActionAssertions">A reference to the method or property.</param>
/// <typeparam name="TException">
/// The type of the exception it should throw.
/// </typeparam>
/// <param name="because">
/// A formatted phrase explaining why the assertion should be satisfied. If the phrase does not
/// start with the word <i>because</i>, it is prepended to the message.
/// </param>
/// <param name="becauseArgs">
/// Zero or more values to use for filling in any <see cref="string.Format(string,object[])"/> compatible placeholders.
/// </param>
/// <returns>
/// Returns an object that allows asserting additional members of the thrown exception.
/// </returns>
public static ExceptionAssertions<TException> ThrowExactly<TException>(
this AsyncActionAssertions asyncActionAssertions,
string because = "",
params object[] becauseArgs)
where TException : Exception
{
var exceptionAssertions = asyncActionAssertions.Throw<TException>(because, becauseArgs);
exceptionAssertions.Which.GetType().Should().Be<TException>(because, becauseArgs);
return exceptionAssertions;
}
/// <summary>
/// Asserts that the <paramref name="asyncActionAssertions"/> subject throws the exact exception (and not a derived exception type).
/// </summary>
/// <param name="asyncActionAssertions">A reference to the method or property.</param>
/// <typeparam name="TException">
/// The type of the exception it should throw.
/// </typeparam>
/// <param name="because">
/// A formatted phrase explaining why the assertion should be satisfied. If the phrase does not
/// start with the word <i>because</i>, it is prepended to the message.
/// </param>
/// <param name="becauseArgs">
/// Zero or more values to use for filling in any <see cref="string.Format(string,object[])"/> compatible placeholders.
/// </param>
/// <returns>
/// Returns an object that allows asserting additional members of the thrown exception.
/// </returns>
public static async Task<ExceptionAssertions<TException>> ThrowExactlyAsync<TException>(
this AsyncActionAssertions asyncActionAssertions,
string because = "",
params object[] becauseArgs)
where TException : Exception
{
var exceptionAssertions = await asyncActionAssertions.ThrowAsync<TException>(because, becauseArgs);
exceptionAssertions.Which.GetType().Should().Be<TException>(because, becauseArgs);
return exceptionAssertions;
}
private class AggregateExceptionExtractor : IExtractExceptions
{
public IEnumerable<T> OfType<T>(Exception actualException)
where T : Exception
{
if (typeof(T).IsSameOrInherits(typeof(AggregateException)))
{
return (actualException is T exception) ? new[] { exception } : Enumerable.Empty<T>();
}
return GetExtractedExceptions<T>(actualException);
}
private static List<T> GetExtractedExceptions<T>(Exception actualException)
where T : Exception
{
var exceptions = new List<T>();
if (actualException is AggregateException aggregateException)
{
var flattenedExceptions = aggregateException.Flatten();
exceptions.AddRange(flattenedExceptions.InnerExceptions.OfType<T>());
}
else if (actualException is T genericException)
{
exceptions.Add(genericException);
}
return exceptions;
}
}
}
}