PageRenderTime 48ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/src/NUnit/core/ExpectedExceptionProcessor.cs

#
C# | 279 lines | 214 code | 37 blank | 28 comment | 23 complexity | 2a44e35c17ec7ee795f0c1b5595ca128 MD5 | raw file
Possible License(s): GPL-2.0
  1. // ****************************************************************
  2. // Copyright 2008, Charlie Poole
  3. // This is free software licensed under the NUnit license. You may
  4. // obtain a copy of the license at http://nunit.org.
  5. // ****************************************************************
  6. using System;
  7. using System.Reflection;
  8. using System.Text.RegularExpressions;
  9. namespace NUnit.Core
  10. {
  11. public class ExpectedExceptionProcessor
  12. {
  13. #region Fields
  14. /// <summary>
  15. /// The TestMethod to which this exception processor applies
  16. /// </summary>
  17. internal TestMethod testMethod;
  18. /// <summary>
  19. /// The exception handler method
  20. /// </summary>
  21. internal MethodInfo exceptionHandler;
  22. /// <summary>
  23. /// The type of any expected exception
  24. /// </summary>
  25. internal Type expectedExceptionType;
  26. /// <summary>
  27. /// The full name of any expected exception type
  28. /// </summary>
  29. internal string expectedExceptionName;
  30. /// <summary>
  31. /// The value of any message associated with an expected exception
  32. /// </summary>
  33. internal string expectedMessage;
  34. /// <summary>
  35. /// A string indicating how to match the expected message
  36. /// </summary>
  37. internal string matchType;
  38. /// <summary>
  39. /// A string containing any user message specified for the expected exception
  40. /// </summary>
  41. internal string userMessage;
  42. #endregion
  43. #region Constructor
  44. public ExpectedExceptionProcessor( TestMethod testMethod )
  45. {
  46. this.testMethod = testMethod;
  47. }
  48. public ExpectedExceptionProcessor(TestMethod testMethod, object source)
  49. {
  50. this.testMethod = testMethod;
  51. this.expectedExceptionType = GetExceptionType(source);
  52. this.expectedExceptionName = GetExceptionName(source);
  53. this.expectedMessage = GetExpectedMessage(source);
  54. this.matchType = GetMatchType(source);
  55. this.userMessage = GetUserMessage(source);
  56. string handlerName = GetHandler(source);
  57. if (handlerName == null)
  58. this.exceptionHandler = GetDefaultExceptionHandler(testMethod.FixtureType);
  59. else
  60. {
  61. MethodInfo handler = GetExceptionHandler(testMethod.FixtureType, handlerName);
  62. if (handler != null)
  63. this.exceptionHandler = handler;
  64. else
  65. {
  66. testMethod.RunState = RunState.NotRunnable;
  67. testMethod.IgnoreReason = string.Format(
  68. "The specified exception handler {0} was not found", handlerName);
  69. }
  70. }
  71. }
  72. #endregion
  73. #region Public Methods
  74. public void ProcessNoException(TestResult testResult)
  75. {
  76. testResult.Failure(NoExceptionMessage(), null);
  77. }
  78. public void ProcessException(Exception exception, TestResult testResult)
  79. {
  80. if (exception is NUnitException)
  81. exception = exception.InnerException;
  82. if (IsExpectedExceptionType(exception))
  83. {
  84. if (IsExpectedMessageMatch(exception))
  85. {
  86. if (exceptionHandler != null)
  87. Reflect.InvokeMethod(exceptionHandler, testMethod.Fixture, exception);
  88. testResult.Success();
  89. }
  90. else
  91. {
  92. testResult.Failure(WrongTextMessage(exception), GetStackTrace(exception));
  93. }
  94. }
  95. else
  96. {
  97. switch (NUnitFramework.GetResultState(exception))
  98. {
  99. case ResultState.Failure:
  100. testResult.Failure(exception.Message, exception.StackTrace);
  101. break;
  102. case ResultState.Ignored:
  103. testResult.Ignore(exception);
  104. break;
  105. case ResultState.Inconclusive:
  106. testResult.SetResult(ResultState.Inconclusive, exception, FailureSite.Test);
  107. break;
  108. case ResultState.Success:
  109. testResult.Success(exception.Message);
  110. break;
  111. default:
  112. testResult.Failure(WrongTypeMessage(exception), GetStackTrace(exception));
  113. break;
  114. }
  115. }
  116. }
  117. #endregion
  118. #region Helper Methods
  119. private bool IsExpectedExceptionType(Exception exception)
  120. {
  121. return expectedExceptionName == null ||
  122. expectedExceptionName.Equals(exception.GetType().FullName);
  123. }
  124. private bool IsExpectedMessageMatch(Exception exception)
  125. {
  126. if (expectedMessage == null)
  127. return true;
  128. switch (matchType)
  129. {
  130. case "Exact":
  131. default:
  132. return expectedMessage.Equals(exception.Message);
  133. case "Contains":
  134. return exception.Message.IndexOf(expectedMessage) >= 0;
  135. case "Regex":
  136. return Regex.IsMatch(exception.Message, expectedMessage);
  137. case "StartsWith":
  138. return exception.Message.StartsWith(expectedMessage);
  139. }
  140. }
  141. private string NoExceptionMessage()
  142. {
  143. string expectedType = expectedExceptionName == null ? "An Exception" : expectedExceptionName;
  144. return CombineWithUserMessage(expectedType + " was expected");
  145. }
  146. private string WrongTypeMessage(Exception exception)
  147. {
  148. return CombineWithUserMessage(
  149. "An unexpected exception type was thrown" + Environment.NewLine +
  150. "Expected: " + expectedExceptionName + Environment.NewLine +
  151. " but was: " + exception.GetType().FullName + " : " + exception.Message);
  152. }
  153. private string WrongTextMessage(Exception exception)
  154. {
  155. string expectedText;
  156. switch (matchType)
  157. {
  158. default:
  159. case "Exact":
  160. expectedText = "Expected: ";
  161. break;
  162. case "Contains":
  163. expectedText = "Expected message containing: ";
  164. break;
  165. case "Regex":
  166. expectedText = "Expected message matching: ";
  167. break;
  168. case "StartsWith":
  169. expectedText = "Expected message starting: ";
  170. break;
  171. }
  172. return CombineWithUserMessage(
  173. "The exception message text was incorrect" + Environment.NewLine +
  174. expectedText + expectedMessage + Environment.NewLine +
  175. " but was: " + exception.Message);
  176. }
  177. private string CombineWithUserMessage(string message)
  178. {
  179. if (userMessage == null)
  180. return message;
  181. return userMessage + Environment.NewLine + message;
  182. }
  183. private string GetStackTrace(Exception exception)
  184. {
  185. try
  186. {
  187. return exception.StackTrace;
  188. }
  189. catch (Exception)
  190. {
  191. return "No stack trace available";
  192. }
  193. }
  194. private static MethodInfo GetDefaultExceptionHandler(Type fixtureType)
  195. {
  196. return Reflect.HasInterface(fixtureType, NUnitFramework.ExpectExceptionInterface)
  197. ? GetExceptionHandler(fixtureType, "HandleException")
  198. : null;
  199. }
  200. private static MethodInfo GetExceptionHandler(Type fixtureType, string name)
  201. {
  202. return Reflect.GetNamedMethod(
  203. fixtureType,
  204. name,
  205. new string[] { "System.Exception" });
  206. }
  207. private static string GetHandler(object source)
  208. {
  209. return Reflect.GetPropertyValue(source, "Handler") as string;
  210. }
  211. private static Type GetExceptionType(object source)
  212. {
  213. Type type = Reflect.GetPropertyValue(source, PropertyNames.ExpectedException) as Type;
  214. // Prior to 2.5, NUnit used an 'ExceptionType' property
  215. if (type == null)
  216. type = Reflect.GetPropertyValue(source, PropertyNames.LegacyExceptionType) as Type;
  217. return type;
  218. }
  219. private static string GetExceptionName(object source)
  220. {
  221. string name = Reflect.GetPropertyValue(source, PropertyNames.ExpectedExceptionName) as string;
  222. // Prior to 2.5, NUnit used an 'ExceptionName' property
  223. if (name == null)
  224. name = Reflect.GetPropertyValue(source, PropertyNames.LegacyExceptionName) as string;
  225. return name;
  226. }
  227. private static string GetExpectedMessage(object source)
  228. {
  229. return Reflect.GetPropertyValue(source, PropertyNames.ExpectedMessage) as string;
  230. }
  231. private static string GetMatchType(object source)
  232. {
  233. object matchEnum = Reflect.GetPropertyValue(source, "MatchType");
  234. return matchEnum != null ? matchEnum.ToString() : null;
  235. }
  236. private static string GetUserMessage(object source)
  237. {
  238. return Reflect.GetPropertyValue(source, "UserMessage") as string;
  239. }
  240. #endregion
  241. }
  242. }