PageRenderTime 78ms CodeModel.GetById 64ms app.highlight 11ms RepoModel.GetById 1ms app.codeStats 0ms

/src/NUnit/core/ExpectedExceptionProcessor.cs

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