/// <summary> /// Provides the ability to raise an event that has had an expectation created /// </summary> /// <typeparam name="T">the mocked type</typeparam> /// <param name="instance">the mocked instance</param> /// <param name="eventSubscription">the event that has had an expectation created</param> /// <param name="args">arguments used to the raise event</param> /// <returns>collection of the actual calls</returns> /// <exception cref="System.ArgumentNullException">thrown when the instance is null</exception> /// <exception cref="System.ArgumentOutOfRangeException"> /// thrown when the instance cannot be identified as a mocked object or the given method is not an event /// </exception> public static void Raise <T>(this T instance, Action <T> eventSubscription, object[] args) where T : class { if (instance == null) { throw new ArgumentNullException("instance", "Events cannot be raised from a null object or instance."); } var container = GetExpectationContainer(instance); if (container == null) { throw new ArgumentOutOfRangeException("instance", "Events can only be raised from a mocked object or instance."); } var expectation = new ExpectEvent(); container.MarkForAssertion(expectation); try { eventSubscription(instance); } catch (Exception ex) { throw new InvalidOperationException("Exception caught while identifying event", ex); } if (container.ExpectationMarked) { throw new InvalidOperationException(); } var method = expectation.Method; if (!method.IsSpecialName) { throw new InvalidOperationException("Raise method can only be used against events."); } var methodName = method.Name; if (!methodName.StartsWith("add_")) { throw new InvalidOperationException("Raise method can only be used against events."); } var eventName = methodName.Substring(4); var subscription = container.GetEventSubscribers(eventName); if (subscription == null) { return; } var raiser = new EventRaiser(instance); raiser.Raise(subscription, args); }
/// <summary> /// Creates an stub against the mocked object for an event to provide /// the ability to raise the event /// </summary> /// <example> /// The following is an example of how to setup a stub against an event: /// <code> /// [Fact] /// public void Test() { /// var mock = MockRepository.Mock{Page}(); /// mock.StubEvent(x => x.OnLoad += null); /// } /// </code> /// </example> /// <remarks> /// Applicable for events only /// </remarks> /// <typeparam name="T">the mocked type</typeparam> /// <param name="instance">the mocked instance</param> /// <param name="action">the event to create the stub against</param> /// <returns>stub targeted for events</returns> /// <exception cref="System.ArgumentNullException">thrown when the instance is null</exception> /// <exception cref="System.ArgumentOutOfRangeException">thrown when the instance cannot be identified as a mocked object</exception> /// <exception cref="System.InvalidOperationException"> /// thrown when the event cannot be resolved or the given method is not an event /// </exception> public static IEventOptions StubEvent <T>(this T instance, Action <T> action) where T : class { if (instance == null) { throw new ArgumentNullException("instance", "Stubs cannot be set on a null object or instance."); } var container = GetExpectationContainer(instance); if (container == null) { throw new ArgumentOutOfRangeException("instance", "Stubs can only be set on a mocked object or instance."); } var expectation = new ExpectEvent(); expectation.SetExpectedCount(new Range(int.MaxValue, int.MaxValue)); container.MarkForExpectation(expectation); try { action(instance); } catch (Exception ex) { throw new InvalidOperationException("Exception caught while setting up stub", ex); } if (container.ExpectationMarked) { throw new InvalidOperationException(); } var method = expectation.Method; if (!method.IsSpecialName) { throw new InvalidOperationException("StubEvent method can only be used against events."); } var methodName = method.Name; if (!methodName.StartsWith("add_") && !methodName.StartsWith("remove_")) { throw new InvalidOperationException("StubEvent method can only be used against events."); } return(expectation); }
/// <summary> /// Check the result to make sure it is valid. /// </summary> /// <param name="result">The <see cref="WebApiAgentResult"/>.</param> /// <param name="sw">The <see cref="Stopwatch"/> used to measure <see cref="WebApiAgentBase"/> invocation.</param> protected void ResultCheck(WebApiAgentResult result, Stopwatch sw) { if (result == null) { throw new ArgumentNullException(nameof(result)); } // Log to output. TestContext.Out.WriteLine(""); TestContext.Out.WriteLine("AGENT TESTER..."); TestContext.Out.WriteLine(""); TestContext.Out.WriteLine($"REQUEST >"); TestContext.Out.WriteLine($"Request: {result.Request.Method} {result.Request.RequestUri}"); if (!string.IsNullOrEmpty(Username)) { TestContext.Out.WriteLine($"Username: {Username}"); } TestContext.Out.WriteLine($"Headers: {(result.Request.Headers == null || !result.Request.Headers.Any() ? "none" : "")}"); if (result.Request.Headers != null && result.Request.Headers.Any()) { foreach (var hdr in result.Request.Headers) { var sb = new StringBuilder(); foreach (var v in hdr.Value) { if (sb.Length > 0) { sb.Append(", "); } sb.Append(v); } TestContext.Out.WriteLine($" {hdr.Key}: {sb}"); } } JToken?json = null; if (result.Request.Content != null) { // HACK: The Request Content is a forward only stream that is already read; we need to reset this private variable back to the start. if (result.Request.Content is StreamContent) { var fi = typeof(StreamContent).GetField("_content", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic); var ms = (MemoryStream)fi !.GetValue(result.Request.Content) !; ms.Position = 0; } // Parse out the content. try { json = JToken.Parse(result.Request.Content.ReadAsStringAsync().Result); } #pragma warning disable CA1031 // Do not catch general exception types; by-design. catch (Exception) { } #pragma warning restore CA1031 TestContext.Out.WriteLine($"Content: [{result.Request.Content?.Headers?.ContentType?.MediaType ?? "None"}]"); TestContext.Out.WriteLine(json == null ? result.Request.Content?.ToString() : json.ToString()); } TestContext.Out.WriteLine(""); TestContext.Out.WriteLine($"RESPONSE >"); TestContext.Out.WriteLine($"HttpStatusCode: {result.StatusCode} ({(int)result.StatusCode})"); TestContext.Out.WriteLine($"Elapsed (ms): {(sw == null ? "none" : sw.ElapsedMilliseconds.ToString(System.Globalization.CultureInfo.InvariantCulture))}"); var hdrs = result.Response?.Headers?.ToString().Split(Environment.NewLine, StringSplitOptions.RemoveEmptyEntries); TestContext.Out.WriteLine($"Headers: {(hdrs == null || !hdrs.Any() ? "none" : "")}"); if (hdrs != null && hdrs.Any()) { foreach (var hdr in hdrs) { TestContext.Out.WriteLine($" {hdr}"); } } TestContext.Out.WriteLine($"Messages: {(result.Messages == null || result.Messages.Count == 0 ? "none" : "")}"); if (result.Messages != null && result.Messages.Count > 0) { foreach (var m in result.Messages) { TestContext.Out.WriteLine($" {m.Type}: {m.Text} {(m.Property == null ? "" : "(" + m.Property + ")")}"); } TestContext.Out.WriteLine(""); } json = null; if (!string.IsNullOrEmpty(result.Content) && result.Response?.Content?.Headers?.ContentType?.MediaType == "application/json") { try { json = JToken.Parse(result.Content); } #pragma warning disable CA1031 // Do not catch general exception types; by-design. catch (Exception) { /* This is being swallowed by design. */ } #pragma warning restore CA1031 } TestContext.Out.Write($"Content: [{result.Response?.Content?.Headers?.ContentType?.MediaType ?? "none"}]"); if (json != null) { TestContext.Out.WriteLine(""); TestContext.Out.WriteLine(json.ToString()); } else { TestContext.Out.WriteLine($"{(string.IsNullOrEmpty(result.Content) ? "none" : result.Content)}"); } TestContext.Out.WriteLine(""); TestContext.Out.WriteLine($"EVENTS PUBLISHED >"); var events = ExpectEvent.GetEvents(CorrelationId); if (events.Count == 0) { TestContext.Out.WriteLine(" None."); } else { foreach (var e in events) { TestContext.Out.WriteLine($" Subject: {e.Subject}, Action: {e.Action}"); } } TestContext.Out.WriteLine(""); TestContext.Out.WriteLine($"LOGGING >"); var messages = CorrelationIdLogger.GetMessages(CorrelationId); if (messages.Count == 0) { TestContext.Out.WriteLine(" None."); } else { foreach (var l in messages) { TestContext.Out.WriteLine($"{l}"); } } TestContext.Out.WriteLine(""); TestContext.Out.WriteLine(new string('=', 80)); TestContext.Out.WriteLine(""); // Perform checks. if (_expectedStatusCode.HasValue && _expectedStatusCode != result.StatusCode) { Assert.Fail($"Expected HttpStatusCode was '{_expectedStatusCode} ({(int)_expectedStatusCode})'; actual was {result.StatusCode} ({(int)result.StatusCode})."); } if (_expectedErrorType.HasValue && _expectedErrorType != result.ErrorType) { Assert.Fail($"Expected ErrorType was '{_expectedErrorType}'; actual was '{result.ErrorType}'."); } if (_expectedErrorMessage != null && _expectedErrorMessage != result.ErrorMessage) { Assert.Fail($"Expected ErrorMessage was '{_expectedErrorMessage}'; actual was '{result.ErrorMessage}'."); } if (_expectedMessages != null) { ExpectValidationException.CompareExpectedVsActual(_expectedMessages, result.Messages); } }