/// <summary> /// Gets a clone of the original mock for verification purposes. /// </summary> /// <param name="mock">The mock to be cloned.</param> /// <param name="notCalled">Whether to add a behavior that verifies the invocations performed on /// the clone were never performed on the original mock. /// </param> static T GetVerifier <T>(IMock <T> mock, bool notCalled = false) where T : class { // If the mock is already being verified, we don't need to clone again. if (mock.State.TryGetValue <bool>(typeof(Verify), out var verifying) && verifying) { return(mock.Object); } // Otherwise, we create a verification copy that does not record invocations // and has default behavior. var clone = mock.Clone(); var recording = clone.Behaviors.OfType <MockRecordingBehavior>().FirstOrDefault(); if (recording != null) { clone.Behaviors.Remove(recording); } if (notCalled) { clone.Behaviors.Insert( clone.Behaviors.IndexOf(clone.Behaviors.OfType <MockContextBehavior>().First()) + 1, new NotCalledBehavior()); } // Sets up the right behaviors for a loose mock new Moq <T>(clone).Behavior = MockBehavior.Loose; clone.State.Set(typeof(Verify), true); return(clone.Object); }
/// <summary> /// Gets a clone of the original mock for verification purposes. /// </summary> /// <param name="mock">The mock to be cloned.</param> /// <param name="notCalled">Whether to add a behavior that verifies the invocations performed on /// the clone were never performed on the original mock. /// </param> static T GetVerifier <T>(IMock <T> mock, bool notCalled = false) where T : class { // If the mock is already being verified, we don't need to clone again. if (mock.State.TryGetValue <bool>(typeof(Verify), out var verifying) && verifying) { return(mock.Object); } // Otherwise, we create a verification copy that does not record invocations // and has default behavior. var clone = mock.Clone(); var recording = clone.Behaviors.OfType <MockRecordingBehavior>().FirstOrDefault(); if (recording != null) { clone.Behaviors.Remove(recording); } // The target replacer is needed so that whenever we try to get the target object // and the IMock from it for occurrence verification, we actually get to the actual // target being verified, not the cloned mock. Otherwise, invocations won't match // with the setups, since the target would be different. clone.Behaviors.Insert( clone.Behaviors.IndexOf(clone.Behaviors.OfType <MockContextBehavior>().First()) + 1, new TargetReplacerBehavior(mock.Object)); if (notCalled) { clone.Behaviors.Insert( clone.Behaviors.IndexOf(clone.Behaviors.OfType <TargetReplacerBehavior>().First()) + 1, new NotCalledBehavior()); } // Sets up the right behaviors for a loose mock new Moq <T>(clone).Behavior = MockBehavior.Loose; clone.State.Set(typeof(Verify), true); return(clone.Object); }