private static void VerifyCalls( Mock targetMock, MethodCall expected, LambdaExpression expression, Times times) { var allInvocations = targetMock.MutableInvocations.ToArray(); var matchingInvocations = allInvocations.Where(expected.Matches).ToArray(); var matchingInvocationCount = matchingInvocations.Length; if (!times.Verify(matchingInvocationCount)) { var setups = targetMock.Setups.ToArrayLive(oc => AreSameMethod(oc.SetupExpression, expression)); throw MockException.NoMatchingCalls(expected, setups, allInvocations, expression, times, matchingInvocationCount); } else { foreach (var matchingInvocation in matchingInvocations) { matchingInvocation.MarkAsVerified(); } } bool AreSameMethod(LambdaExpression l, LambdaExpression r) => l.Body is MethodCallExpression lc && r.Body is MethodCallExpression rc && lc.Method == rc.Method; }
public override InterceptionAction Handle(Invocation invocation, Mock mock) { var matchedSetup = mock.Setups.FindMatchFor(invocation); if (matchedSetup != null) { matchedSetup.Condition?.EvaluatedSuccessfully(); if (matchedSetup.IsVerifiable) { invocation.MarkAsMatchedByVerifiableSetup(); } else { invocation.MarkAsMatchedBySetup(); } matchedSetup.SetOutParameters(invocation); // We first execute, as there may be a Throws // and therefore we might never get to the // next line. matchedSetup.Execute(invocation); return(InterceptionAction.Stop); } else if (mock.Behavior == MockBehavior.Strict) { throw MockException.NoSetup(invocation); } else { return(InterceptionAction.Continue); } }
internal bool TryVerify(Func <ISetup, bool> predicate, out MockException error) { foreach (Invocation invocation in this.MutableInvocations) { invocation.MarkAsVerifiedIfMatchedBy(predicate); } var errors = new List <MockException>(); foreach (var setup in this.MutableSetups.ToArray(predicate)) { if (predicate(setup) && !setup.TryVerify(recursive: true, predicate, out var e) && e.IsVerificationError) { errors.Add(e); } } if (errors.Count > 0) { error = MockException.Combined( errors, preamble: string.Format(CultureInfo.CurrentCulture, Resources.VerificationErrorsOfMock, this)); return(false); } else { error = null; return(true); } }
private bool TryVerifyAll(out MockException error) { foreach (Invocation invocation in this.MutableInvocations) { invocation.MarkAsVerifiedIfMatchedBySetup(); } var uninvokedSetups = this.Setups.ToArrayLive(setup => !setup.TryVerifyAll()); if (uninvokedSetups.Length > 0) { error = MockException.UnmatchedSetups(this, uninvokedSetups); return(false); } foreach (var inner in this.InnerMocks.Values) { if (!inner.Mock.TryVerifyAll(out error)) { return(false); } } error = null; return(true); }
public override void Execute(Invocation invocation) { base.Execute(invocation); if (this.returnValueKind == ReturnValueKind.CallBase) { invocation.ReturnBase(); } else if (this.valueDel != null) { invocation.Return(this.valueDel.HasCompatibleParameterList(new ParameterInfo[0]) ? valueDel.InvokePreserveStack() //we need this, for the user to be able to use parameterless methods : valueDel.InvokePreserveStack(invocation.Arguments)); //will throw if parameters mismatch } else if (this.Mock.Behavior == MockBehavior.Strict) { throw MockException.ReturnValueRequired(invocation); } else { invocation.Return(this.ReturnType.GetDefaultValue()); } this.afterReturnCallback?.Invoke(invocation.Arguments); }
internal void Verify(Func <ISetup, bool> predicate, HashSet <Mock> verifiedMocks) { if (verifiedMocks.Add(this) == false) { // This mock has already been verified; don't verify it again. // (We can end up here e.g. when there are loops in the inner mock object graph.) return; } foreach (Invocation invocation in this.MutableInvocations) { invocation.MarkAsVerifiedIfMatchedBy(predicate); } var errors = new List <MockException>(); foreach (var setup in this.MutableSetups.ToArray(setup => !setup.IsOverridden && !setup.IsConditional && predicate(setup))) { try { setup.Verify(recursive: true, predicate, verifiedMocks); } catch (MockException error) when(error.IsVerificationError) { errors.Add(error); } } if (errors.Count > 0) { throw MockException.Combined( errors, preamble: string.Format(CultureInfo.CurrentCulture, Resources.VerificationErrorsOfMock, this)); } }
protected virtual void VerifySelf() { if (!this.IsMatched) { throw MockException.UnmatchedSetup(this); } }
public static void Handle(Invocation invocation, Mock mock) { if (mock.Behavior == MockBehavior.Strict) { throw MockException.NoSetup(invocation); } }
internal static void Verify( Mock mock, LambdaExpression expression, Times times, string failMessage ) { Guard.NotNull(times, nameof(times)); var invocationCount = Mock.GetMatchingInvocationCount( mock, expression, out var invocationsToBeMarkedAsVerified ); if (times.Validate(invocationCount)) { foreach (var(invocation, part) in invocationsToBeMarkedAsVerified) { part.SetupEvaluatedSuccessfully(invocation); invocation.MarkAsVerified(); } } else { throw MockException.NoMatchingCalls( mock, expression, failMessage, times, invocationCount ); } }
internal static MockException FromInnerMockOf(Setup setup, MockException error) { var message = new StringBuilder(); message.AppendLine(string.Format(CultureInfo.CurrentCulture, Resources.VerificationErrorsOfInnerMock, setup)).TrimEnd().AppendLine() .AppendLine(); message.AppendIndented(error.Message, count: 3); return(new MockException(error.Reasons, message.ToString())); }
private static void VerifyNoOtherCalls(Mock mock, HashSet <Mock> verifiedMocks) { if (!verifiedMocks.Add(mock)) { return; } var unverifiedInvocations = mock.MutableInvocations.ToArray( invocation => !invocation.IsVerified ); var innerMockSetups = mock.MutableSetups.GetInnerMockSetups(); if (unverifiedInvocations.Any()) { // There are some invocations that shouldn't require explicit verification by the user. // The intent behind a `Verify` call for a call expression like `m.A.B.C.X` is probably // to verify `X`. If that succeeds, it's reasonable to expect that `m.A`, `m.A.B`, and // `m.A.B.C` have implicitly been verified as well. Below, invocations such as those to // the left of `X` are referred to as "transitive" (for lack of a better word). if (innerMockSetups.Any()) { for (int i = 0, n = unverifiedInvocations.Length; i < n; ++i) { // In order for an invocation to be "transitive", its return value has to be a // sub-object (inner mock); and that sub-object has to have received at least // one call: var wasTransitiveInvocation = innerMockSetups.TryFind(unverifiedInvocations[i]) is Setup inner && inner.InnerMock.MutableInvocations.Any(); if (wasTransitiveInvocation) { unverifiedInvocations[i] = null; } } } // "Transitive" invocations have been nulled out. Let's see what's left: var remainingUnverifiedInvocations = unverifiedInvocations.Where(i => i != null); if (remainingUnverifiedInvocations.Any()) { throw MockException.UnverifiedInvocations(mock, remainingUnverifiedInvocations); } } // Perform verification for all automatically created sub-objects (that is, those // created by "transitive" invocations): foreach (var inner in innerMockSetups) { VerifyNoOtherCalls(inner.InnerMock, verifiedMocks); } }
private void Verify(Action <ISetup> verifyLast) { Debug.Assert(verifyLast != null); Debug.Assert(this.parts.Count > 1); try { foreach (var part in this.parts.Take(this.parts.Count - 1)) { part.Verify(recursive: false); } verifyLast(this.parts.Last()); } catch (MockException error) when(error.IsVerificationError) { throw MockException.FromInnerMockOf(this, error); } }
/// <summary> /// Verifies this setup and those of its inner mock (if present and known). /// </summary> /// <param name="recursive"> /// Specifies whether recursive verification should be performed. /// </param> /// <param name="predicate"> /// Specifies which setups should be verified. /// </param> /// <param name="error"> /// If this setup or any of its inner mock (if present and known) failed verification, /// this <see langword="out"/> parameter will receive a <see cref="MockException"/> describing the verification error(s). /// </param> /// <returns> /// <see langword="true"/> if verification succeeded without any errors; /// otherwise, <see langword="false"/>. /// </returns> public bool TryVerify(bool recursive, Func <ISetup, bool> predicate, out MockException error) { MockException e; // verify this setup: if (!this.TryVerifySelf(out e) && e.IsVerificationError) { error = e; return(false); } // optionally verify setups of inner mock (if present and known): if (recursive && this.ReturnsInnerMock(out var innerMock) && !innerMock.TryVerify(predicate, out e) && e.IsVerificationError) { error = MockException.FromInnerMockOf(this, e); return(false); } error = null; return(true); }
/// <summary> /// Verifies this setup and those of its inner mock (if present and known). /// </summary> /// <param name="recursive"> /// Specifies whether recursive verification should be performed. /// </param> /// <param name="predicate"> /// Specifies which setups should be verified. /// </param> /// <param name="verifiedMocks"> /// The set of mocks that have already been verified. /// </param> /// <exception cref="MockException"> /// This setup or any of its inner mock (if present and known) failed verification. /// </exception> internal void Verify(bool recursive, Func <ISetup, bool> predicate, HashSet <Mock> verifiedMocks) { // verify this setup: this.VerifySelf(); // optionally verify setups of inner mock (if present and known): if (recursive) { try { foreach (var innerMock in this.InnerMocks) { innerMock.Verify(predicate, verifiedMocks); } } catch (MockException error) when(error.IsVerificationError) { throw MockException.FromInnerMockOf(this, error); } } }
private bool TryVerifyAll(out MockException error) { var uninvokedSetups = this.Setups.ToArrayLive(setup => !setup.Invoked); if (uninvokedSetups.Length > 0) { error = MockException.UnmatchedSetups(this, uninvokedSetups); return(false); } foreach (var inner in this.InnerMocks.Values) { if (!inner.Mock.TryVerifyAll(out error)) { return(false); } } error = null; return(true); }
internal bool TryVerify(Func <ISetup, bool> predicate, HashSet <Mock> verifiedMocks, out MockException error) { if (verifiedMocks.Add(this) == false) { // This mock has already been verified; don't verify it again. // (We can end up here e.g. when there are loops in the inner mock object graph.) error = null; return(true); } foreach (Invocation invocation in this.MutableInvocations) { invocation.MarkAsVerifiedIfMatchedBy(predicate); } var errors = new List <MockException>(); foreach (var setup in this.MutableSetups.ToArray(predicate)) { if (predicate(setup) && !setup.TryVerify(recursive: true, predicate, verifiedMocks, out var e) && e.IsVerificationError) { errors.Add(e); } } if (errors.Count > 0) { error = MockException.Combined( errors, preamble: string.Format(CultureInfo.CurrentCulture, Resources.VerificationErrorsOfMock, this)); return(false); } else { error = null; return(true); } }
private static void VerifyCalls( Mock targetMock, InvocationShape expectation, LambdaExpression expression, Times times, string failMessage) { var allInvocations = targetMock.MutableInvocations.ToArray(); var matchingInvocations = allInvocations.Where(expectation.IsMatch).ToArray(); var matchingInvocationCount = matchingInvocations.Length; if (!times.Verify(matchingInvocationCount)) { Setup[] setups; if (targetMock.IsDelegateMock) { // For delegate mocks, there's no need to compare methods as for regular mocks (below) // since there's only one single method, so include all setups unconditionally. setups = targetMock.Setups.ToArrayLive(s => true); } else { setups = targetMock.Setups.ToArrayLive(oc => AreSameMethod(oc.Expression, expression)); } throw MockException.NoMatchingCalls(failMessage, setups, allInvocations, expression, times, matchingInvocationCount); } else { foreach (var matchingInvocation in matchingInvocations) { matchingInvocation.MarkAsVerified(); } } bool AreSameMethod(LambdaExpression l, LambdaExpression r) => l.Body is MethodCallExpression lc && r.Body is MethodCallExpression rc && lc.Method == rc.Method; }
private MockException TryVerifySetups(Func <Setup, MockException> verifySetup) { var errors = new List <MockException>(); foreach (var setup in this.Setups.ToArrayLive(_ => true)) { var error = verifySetup(setup); if (error?.IsVerificationError == true) { errors.Add(error); } } if (errors.Count > 0) { return(MockException.Combined( errors, preamble: string.Format(CultureInfo.CurrentCulture, Resources.VerificationErrorsOfMock, this))); } else { return(null); } }
protected override bool TryVerifySelf(out MockException error) { error = null; return(true); }
protected virtual bool TryVerifySelf(out MockException error) { error = this.WasMatched ? null : MockException.UnmatchedSetup(this); return(error == null); }
public override MockException TryVerifyAll() { return(this.invoked ? null : MockException.UnmatchedSetup(this)); }
/// <summary> /// Initializes a new instance of the <see cref="MockSetupMethodNeverUsedException"/> class. This override of the constructor provides a proper error message to describe the reason for the exception. /// </summary> /// <param name="innerException"> /// The inner exception. /// </param> public MockSetupMethodNeverUsedException(MockException innerException) : this(string.Format("Some methods of the mock were setup, but never used.\r\n\r\n{0}", innerException.Message), innerException) { }