1 // -----------------------------------------------------------------------
\r
2 // Copyright (c) Microsoft Corporation. All rights reserved.
\r
3 // -----------------------------------------------------------------------
\r
5 using Microsoft.VisualStudio.TestTools.UnitTesting;
\r
6 using System.Runtime.Serialization;
\r
8 namespace System.UnitTesting
\r
10 public static class ExceptionAssert
\r
12 // NOTE: To catch state corrupting exceptions, it by design that
\r
13 // the ThrowsXXX methods retry by default. To prevent this in a
\r
14 // test, simply use one of the overloads that takes a RetryMode.
\r
17 /// Verifies that the exception has the default message generated by the base Exception class.
\r
19 public static void HasDefaultMessage(Exception exception)
\r
21 Assert.IsNotNull(exception);
\r
23 // Exception of type '[typename]' was thrown
\r
24 StringAssert.Contains(exception.Message, exception.GetType().FullName);
\r
28 /// Verifies that the specified action throws a SerializationException.
\r
30 public static SerializationException ThrowsSerialization(string memberName, Action action)
\r
32 var exception = Throws<SerializationException>(RetryMode.Retry, action, (actual, retryCount) =>
\r
34 AssertSerializationMemberName(memberName, actual, retryCount);
\r
41 /// Verifies that the specified action throws an ObjectDisposedException.
\r
43 public static ObjectDisposedException ThrowsDisposed(object instance, Action action)
\r
45 var exception = Throws<ObjectDisposedException>(RetryMode.Retry, action, (actual, retryCount) =>
\r
47 AssertObjectDisposed(instance, actual, retryCount);
\r
54 /// Verifies that the specified action throws an ArgumentNullException.
\r
56 public static ArgumentNullException ThrowsArgumentNull(string parameterName, Action action)
\r
58 return ThrowsArgument<ArgumentNullException>(parameterName, action);
\r
62 /// Verifies that the specified action throws an ArgumentException.
\r
64 public static ArgumentException ThrowsArgument(string parameterName, Action action)
\r
66 return ThrowsArgument<ArgumentException>(parameterName, action);
\r
70 /// Verifies that the specified action throws an ArgumentException of type <typeparam name="T"/>.
\r
72 public static T ThrowsArgument<T>(string parameterName, Action action)
\r
73 where T : ArgumentException
\r
75 var exception = Throws<T>(RetryMode.Retry, action, (actual, retryCount) =>
\r
77 AssertSameParameterName(parameterName, actual, retryCount);
\r
84 /// Verifies that the specified action throws an exception of type <typeparam name="T"/>,
\r
85 /// with the specified inner exception of type <typeparam name="TInner"/>.
\r
87 public static T Throws<T, TInner>(Action action)
\r
89 where TInner : Exception
\r
91 return Throws<T, TInner>(RetryMode.Retry, action);
\r
95 /// Verifies that the specified action throws an exception of type <typeparam name="T"/>,
\r
96 /// with the specified inner exception of type <typeparam name="TInner"/>, and indicating
\r
97 /// whether to retry.
\r
99 public static T Throws<T, TInner>(RetryMode retry, Action action)
\r
100 where T : Exception
\r
101 where TInner : Exception
\r
103 return Throws<T, TInner>(retry, action, (Action<T, int>)null);
\r
107 /// Verifies that the specified action throws an exception of type <typeparam name="T"/>,
\r
108 /// with the specified inner exception of type <typeparam name="TInner"/>, indicating
\r
109 /// whether to retry and running the specified validator.
\r
111 public static T Throws<T, TInner>(RetryMode retry, Action action, Action<T, int> validator)
\r
112 where T : Exception
\r
113 where TInner : Exception
\r
115 var exception = Throws<T>(retry, action, (actual, retryCount) =>
\r
117 AssertIsExactInstanceOfInner(typeof(TInner), actual, retryCount);
\r
119 if (validator != null)
\r
121 validator(actual, retryCount);
\r
129 /// Verifies that the specified action throws an exception of type <typeparam name="T"/>,
\r
130 /// with the specified inner exception.
\r
132 public static T Throws<T>(Exception innerException, Action action)
\r
133 where T : Exception
\r
135 return Throws<T>(innerException, RetryMode.Retry, action, (Action<T, int>)null);
\r
139 /// Verifies that the specified action throws an exception of type <typeparam name="T"/>,
\r
140 /// with the specified inner exception, and indicating whether to retry.
\r
142 public static T Throws<T>(Exception innerException, RetryMode retry, Action action)
\r
143 where T : Exception
\r
145 return Throws<T>(innerException, RetryMode.Retry, action, (Action<T, int>)null);
\r
149 /// Verifies that the specified action throws an exception of type <typeparam name="T"/>,
\r
150 /// with the specified inner exception, indicating whether to retry and running the
\r
151 /// specified validator.
\r
153 public static T Throws<T>(Exception innerException, RetryMode retry, Action action, Action<T, int> validator)
\r
154 where T : Exception
\r
156 T exception = Throws<T>(retry, action, (actual, retryCount) =>
\r
158 AssertSameInner(innerException, actual, retryCount);
\r
160 if (validator != null)
\r
162 validator(actual, retryCount);
\r
170 /// Verifies that the specified action throws an exception of type <typeparam name="T"/>.
\r
172 public static T Throws<T>(Action action)
\r
173 where T : Exception
\r
175 return Throws<T>(RetryMode.Retry, action, (Action<T, int>)null);
\r
179 /// Verifies that the specified action throws an exception of type <typeparam name="T"/>,
\r
180 /// indicating whether to retry.
\r
182 public static T Throws<T>(RetryMode retry, Action action)
\r
183 where T : Exception
\r
185 return Throws<T>(retry, action, (Action<T, int>)null);
\r
189 /// Verifies that the specified action throws an exception of type <typeparam name="T"/>,
\r
190 /// indicating whether to retry and running the specified validator.
\r
192 public static T Throws<T>(RetryMode retry, Action action, Action<T, int> validator)
\r
193 where T : Exception
\r
195 var exception = (T)Run(retry, action, (actual, retryCount) =>
\r
197 AssertIsExactInstanceOf(typeof(T), actual, retryCount);
\r
199 if (validator != null)
\r
201 validator((T)actual, retryCount);
\r
209 /// Verifies that the specified action throws the specified exception.
\r
211 public static void Throws(Exception expected, Action action)
\r
213 Throws(expected, RetryMode.Retry, action);
\r
217 /// Verifies that the specified action throws the specified exception,
\r
218 /// indicating whether to retry.
\r
220 public static void Throws(Exception expected, RetryMode retry, Action action)
\r
222 Throws(expected, retry, action, (Action<Exception, int>)null);
\r
226 /// Verifies that the specified action throws the specified exception,
\r
227 /// indicating whether to retry and running the specified validator.
\r
229 public static void Throws(Exception expected, RetryMode retry, Action action, Action<Exception, int> validator)
\r
231 Run(retry, action, (actual, retryCount) =>
\r
233 AssertSame(expected, actual, retryCount);
\r
235 if (validator != null)
\r
237 validator(actual, retryCount);
\r
242 private static Exception Run(RetryMode retry, Action action, Action<Exception, int> validator)
\r
244 Exception exception = null;
\r
246 for (int i = -1; i < (int)retry; i++)
\r
248 exception = Run(action);
\r
250 validator(exception, i + 2);
\r
256 private static Exception Run(Action action)
\r
263 catch (Exception ex)
\r
269 private static void AssertSerializationMemberName(string memberName, SerializationException actual, int retryCount)
\r
271 // Unfortunately, SerializationException does not provide a way to get our hands on the
\r
272 // the actual member that was missing from the SerializationInfo, so we need to grok the
\r
275 // Member '[memberName]' was not found.
\r
276 StringAssert.Contains(actual.Message, "'" + memberName + "'", "Retry Count {0}: Expected SerializationException MemberName to be '{1}'", retryCount, memberName);
\r
279 private static void AssertObjectDisposed(object instance, ObjectDisposedException actual, int retryCount)
\r
281 string objectName = instance.GetType().FullName;
\r
283 Assert.AreEqual(objectName, actual.ObjectName, "Retry Count {0}: Expected {1}.ObjectName to be '{2}', however, '{3}' is.", retryCount, actual.GetType().Name, objectName, actual.ObjectName);
\r
286 private static void AssertSameParameterName(string parameterName, ArgumentException actual, int retryCount)
\r
289 Assert.AreEqual(parameterName, actual.ParamName, "Retry Count {0}: Expected {1}.ParamName to be '{2}', however, '{3}' is.", retryCount, actual.GetType().Name, parameterName, actual.ParamName);
\r
291 // Silverlight doesn't have ArgumentException.ParamName
\r
292 StringAssert.Contains(actual.Message, parameterName, "Retry Count {0}: Expected {1}.ParamName to be '{2}'", retryCount, actual.GetType().Name, parameterName);
\r
296 private static void AssertSame(Exception expected, Exception actual, int retryCount)
\r
298 Assert.AreSame(expected, actual, "Retry Count {0}: Expected '{1}' to be thrown, however, '{2}' was thrown.", retryCount, expected, actual);
\r
301 private static void AssertSameInner(Exception innerException, Exception actual, int retryCount)
\r
303 Assert.AreSame(innerException, actual.InnerException, "Retry Count {0}: Expected '{1}' to be the inner exception, however, '{2}' is.", retryCount, innerException, actual.InnerException);
\r
306 private static void AssertIsExactInstanceOf(Type expectedType, Exception actual, int retryCount)
\r
308 if (actual == null)
\r
309 Assert.Fail("Retry Count {0}: Expected '{1}' to be thrown", retryCount, expectedType);
\r
311 Type actualType = actual.GetType();
\r
313 Assert.AreSame(expectedType, actualType, "Retry Count {0}: Expected '{1}' to be thrown, however, '{2}' was thrown.", retryCount, expectedType, actualType);
\r
316 private static void AssertIsExactInstanceOfInner(Type expectedType, Exception actual, int retryCount)
\r
318 if (actual.InnerException == null)
\r
319 Assert.Fail("Retry Count {0}: Expected '{1}' be the inner exception, however, it is null.", retryCount, expectedType);
\r
321 Type actualType = actual.InnerException.GetType();
\r
323 Assert.AreSame(expectedType, actualType, "Retry Count {0}: Expected '{1}' to be the inner exception, however, '{2}' is.", retryCount, expectedType, actualType);
\r