internal object GetDefaultValue(MethodInfo method, DefaultValueProvider useAlternateProvider = null) { Debug.Assert(method != null); Debug.Assert(method.ReturnType != null); Debug.Assert(method.ReturnType != typeof(void)); if (this.ConfiguredDefaultValues.TryGetValue(method.ReturnType, out object configuredDefaultValue)) { return(configuredDefaultValue); } var result = (useAlternateProvider ?? this.DefaultValueProvider).GetDefaultReturnValue(method, this); var unwrappedResult = TryUnwrapResultFromCompletedTaskRecursively(result); if (unwrappedResult is IMocked unwrappedMockedResult) { // TODO: Perhaps the following `InnerMocks` update isn't in quite the right place yet. // There are two main places in Moq where `InnerMocks` are used: `Mock<T>.FluentMock` and // the `HandleMockRecursion` interception strategy. Both places first query `InnerMocks`, // and if no value for a given member is present, the default value provider get invoked // via the present method. Querying and updating `InnerMocks` is thus spread over two // code locations and therefore non-atomic. It would be good if those could be combined // (`InnerMocks.GetOrAdd`), but that might not be easily possible since `InnerMocks` is // only mocks while default value providers can also return plain, unmocked values. this.InnerMocks.TryAdd(method, new MockWithWrappedMockObject(unwrappedMockedResult.Mock, result)); } return(result); }
public InvocationObservation(Mock mock, Invocation invocation) { this.Mock = mock; this.Invocation = invocation; this.defaultValueProvider = mock.DefaultValueProvider; mock.DefaultValueProvider = DefaultValueProvider.Mock; }
public MockInvocation(Mock mock, Invocation invocation, Match matcher) { this.Mock = mock; this.Invocation = invocation; this.Match = matcher; this.defaultValueProvider = mock.DefaultValueProvider; // Temporarily set mock default value to Mock so that recursion works. mock.DefaultValue = DefaultValue.Mock; }
public Mock(MockBehavior behavior, params object[] args) { if (args == null) { args = new object[] { null }; } this.additionalInterfaces = new List <Type>(); this.behavior = behavior; this.configuredDefaultValues = new Dictionary <Type, object>(); this.constructorArguments = args; this.defaultValueProvider = DefaultValueProvider.Empty; this.eventHandlers = new EventHandlerCollection(); this.innerMocks = new ConcurrentDictionary <MethodInfo, MockWithWrappedMockObject>(); this.invocations = new InvocationCollection(); this.name = CreateUniqueDefaultMockName(); this.setups = new SetupCollection(); this.switches = Switches.Default; this.CheckParameters(); }
/// <summary> /// Invokes the given delegate when the method being set up is invoked, typically used /// to access and set ref/out arguments in a typed fashion. Used in combination /// with <see cref="SetupExtension.Setup{TDelegate}(object, TDelegate)"/>. /// </summary> /// <typeparam name="TDelegate">The lambda to invoke when the setup method runs.</typeparam> /// <param name="target">The setup being performed.</param> /// <param name="handler">The lambda to invoke when the setup is matched.</param> public static void Returns <TDelegate>(this ISetup <TDelegate> target, TDelegate handler) { if (handler is not Delegate @delegate) { throw new ArgumentException(ThisAssembly.Strings.Returns.DelegateExpected, nameof(handler)); } using (new SetupScope()) { // Simulate Any<T> matchers for each member parameter var parameters = @delegate.Method.GetParameters(); object?[] arguments = new object[parameters.Length]; var defaultValue = new DefaultValueProvider(false); for (var i = 0; i < arguments.Length; i++) { var parameter = parameters[i]; MockSetup.Push(new AnyMatcher(parameter.IsOut ? parameter.ParameterType.GetElementType() : parameter.ParameterType)); if (!parameter.IsOut) { arguments[i] = defaultValue.GetDefault(parameter.ParameterType); } } target.Delegate.DynamicInvoke(arguments); // Now we'd have a setup in place and an actual invocation. var setup = MockContext.CurrentSetup; if (setup != null) { setup.Invocation.Target .AsMock() .GetPipeline(setup) .Behaviors.Add(new ReturnsDelegateBehavior(@delegate)); } } }
/// <summary> /// Initializes the repository with the given <paramref name="defaultBehavior"/> /// for newly created mocks from the repository. /// </summary> /// <param name="defaultBehavior">The behavior to use for mocks created /// using the <see cref="Create{T}()"/> repository method if not overridden /// by using the <see cref="Create{T}(MockBehavior)"/> overload.</param> public MockRepository(MockBehavior defaultBehavior) { this.defaultBehavior = defaultBehavior; this.defaultValueProvider = DefaultValueProvider.Empty; this.switches = Switches.Default; }
private static void SetupAllPropertiesPexProtected(Mock mock, DefaultValueProvider defaultValueProvider) { var mockType = mock.MockedType; var properties = mockType .GetAllPropertiesInDepthFirstOrder() // ^ Depth-first traversal is important because properties in derived interfaces // that shadow properties in base interfaces should be set up last. This // enables the use case where a getter-only property is redeclared in a derived // interface as a getter-and-setter property. .Where(p => p.CanRead && p.CanOverrideGet() && p.CanWrite == p.CanOverrideSet() && // ^ This condition will be true for two kinds of properties: // (a) those that are read-only; and // (b) those that are writable and whose setter can be overridden. p.GetIndexParameters().Length == 0 && ProxyFactory.Instance.IsMethodVisible(p.GetGetMethod(), out _)) .Distinct(); foreach (var property in properties) { var expression = GetPropertyExpression(mockType, property); var getter = property.GetGetMethod(true); object value = null; bool valueNotSet = true; mock.Setups.Add(new PropertyGetterMethodCall(mock, expression, getter, () => { if (valueNotSet) { object initialValue; try { initialValue = mock.GetDefaultValue(getter, useAlternateProvider: defaultValueProvider); } catch { // Since this method performs a batch operation, a single failure of the default value // provider should not tear down the whole operation. The empty default value provider // is a safe fallback because it does not throw. initialValue = mock.GetDefaultValue(getter, useAlternateProvider: DefaultValueProvider.Empty); } if (initialValue is IMocked mocked) { SetupAllPropertiesPexProtected(mocked.Mock, defaultValueProvider); } value = initialValue; valueNotSet = false; } return(value); })); if (property.CanWrite) { mock.Setups.Add(new PropertySetterMethodCall(mock, expression, property.GetSetMethod(true), (newValue) => { value = newValue; valueNotSet = false; })); } } }