/// <summary> /// Checks the last method invocation on the mock; /// if Add was invoked the unexpected match is set up; /// </summary> /// <param name="invocation">The proxied method invocation.</param> public void Intercept(IInvocation invocation) { try { invocation.Proceed(); } finally { if (invocation.ReturnValue != null && invocation.ReturnValue is IInvocationList mockInvocations) { if (mockInvocations.Any() && mockInvocations.Last().Method.Name.Equals("Add")) { Logger.LogDebug("I have detected that the previous mock invocation was an add"); var lastInvocation = mockInvocations.Last(); var methodInfo = lastInvocation.Method; var args = lastInvocation.Arguments; //We have everything we need to set up a match, so let's do it var key = args[0].ToString(); var value = args[1]; ProjectReflectionShortcuts.SetUpCacheEntryMethod(value.GetType()).Invoke(null, new[] { ((Mock <IAppCache>)invocation.Proxy).Object, key, value }); } } } }
internal static IAppCache SetUpCacheEntryGet <T>(this IAppCache mockedCachingService, string cacheEntryKey, T cacheEntryValue) { EnsureArgument.IsNotNull(mockedCachingService, nameof(mockedCachingService)); EnsureArgument.IsNotNullOrEmpty(cacheEntryKey, nameof(cacheEntryKey)); Logger.LogDebug("Setting up cache entry Get/GetOrAdd for '{cacheEntryKey}' (type: '{type}'; value: '{cacheEntryValue}')", cacheEntryKey, typeof(T), cacheEntryValue); var cachingServiceMock = Mock.Get(mockedCachingService); cachingServiceMock.Setup(m => m.Get <T>(It.Is <string>(s => s.Equals(cacheEntryKey)))).Callback(() => Logger.LogDebug("Cache Get invoked")).Returns(cacheEntryValue); cachingServiceMock.Setup(m => m.GetOrAdd(It.Is <string>(s => s.Equals(cacheEntryKey)), It.IsAny <Func <ICacheEntry, T> >())) .Callback(() => Logger.LogDebug("Cache GetOrAdd invoked")) .Returns(cacheEntryValue); //Backwards compatibility if (ProjectReflectionShortcuts.GetOrAddWithMemoryCacheEntryOptionsMethod != null) { Logger.LogDebug("Setting up GetOrAddWithMemoryCacheEntryOptionsMethod"); var getOrAddExpression = ExpressionHelper.CreateMethodCallExpression <IAppCache, T>( ProjectReflectionShortcuts.GetOrAddWithMemoryCacheEntryOptionsMethod.MakeGenericMethod(typeof(T)), Expression.Call(ProjectReflectionShortcuts.ItIsMethodWithExpressionOfFuncOfTValueAndBoolArgument(typeof(string)), ExpressionHelper.CreateMethodCallExpression <string, bool>(CoreReflectionShortcuts.StringEqualsMethodWithStringArgument, Expression.Constant(cacheEntryKey, typeof(string)))), Expression.Call(ProjectReflectionShortcuts.ItIsAnyMethod(typeof(Func <ICacheEntry, T>))), Expression.Call(ProjectReflectionShortcuts.ItIsAnyMethod(typeof(MemoryCacheEntryOptions)))); cachingServiceMock.Setup(getOrAddExpression).Callback(() => Logger.LogDebug("Cache GetOrAdd invoked")).Returns(cacheEntryValue); } cachingServiceMock.Setup(m => m.GetAsync <T>(It.Is <string>(s => s.Equals(cacheEntryKey)))) .Callback(() => Logger.LogDebug("Cache GetAsync invoked")) .Returns(Task.FromResult(cacheEntryValue)); cachingServiceMock.Setup(m => m.GetOrAddAsync(It.Is <string>(s => s.Equals(cacheEntryKey)), It.IsAny <Func <ICacheEntry, Task <T> > >())) .Callback(() => Logger.LogDebug("Cache GetOrAddAsync invoked")) .Returns(Task.FromResult(cacheEntryValue)); //Backwards compatibility if (ProjectReflectionShortcuts.GetOrAddAsyncWithMemoryCacheEntryOptionsMethod != null) { Logger.LogDebug("Setting up GetOrAddAsyncWithMemoryCacheEntryOptionsMethod"); var getOrAddAsyncExpression = ExpressionHelper.CreateMethodCallExpression <IAppCache, Task <T> >( ProjectReflectionShortcuts.GetOrAddAsyncWithMemoryCacheEntryOptionsMethod.MakeGenericMethod(typeof(T)), Expression.Call(ProjectReflectionShortcuts.ItIsMethodWithExpressionOfFuncOfTValueAndBoolArgument(typeof(string)), ExpressionHelper.CreateMethodCallExpression <string, bool>(CoreReflectionShortcuts.StringEqualsMethodWithStringArgument, Expression.Constant(cacheEntryKey, typeof(string)))), Expression.Call(ProjectReflectionShortcuts.ItIsAnyMethod(typeof(Func <ICacheEntry, Task <T> >))), Expression.Call(ProjectReflectionShortcuts.ItIsAnyMethod(typeof(MemoryCacheEntryOptions)))); cachingServiceMock.Setup(getOrAddAsyncExpression).Callback(() => Logger.LogDebug("Cache GetOrAddAsync invoked")).Returns(Task.FromResult(cacheEntryValue)); } return(mockedCachingService); }
/// <summary> /// Checks the last method invocation on the mock; /// if GetOrAdd or GetOrAddAsync was invoked the unexpected match is set up and the addItemFactory result will be /// returned; /// otherwise the default value for the specified type will be returned. /// </summary> /// <param name="type">The type of the requested default value.</param> /// <param name="mock">The mock on which an unexpected invocation has occurred.</param> /// <returns> /// if GetOrAdd or GetOrAddAsync was invoked the unexpected match is set up and the addItemFactory result will be /// returned; /// otherwise the default value for the specified type will be returned if the last method invocation has a return /// type. /// </returns> protected override object GetDefaultValue(Type type, Mock mock) { Logger.LogDebug("NoSetUpDefaultValueProvider invoked"); var lastInvocation = mock.Invocations.Last(); var methodInfo = lastInvocation.Method; var args = lastInvocation.Arguments; if (methodInfo.Name.Equals("GetOrAdd")) { //We have everything we need to set up a match, so let's do it var key = args[0].ToString(); var value = args[1].GetType().GetMethod("Invoke").Invoke(args[1], new object[] { new CacheEntryFake(key) }); ProjectReflectionShortcuts.SetUpCacheEntryMethod(value.GetType()).Invoke(null, new[] { _mockedCachingService, key, value }); return(value); } if (methodInfo.Name.Equals("GetOrAddAsync")) { //We have everything we need to set up a match, so let's do it var key = args[0].ToString(); var task = args[1].GetType().GetMethod("Invoke").Invoke(args[1], new object[] { new CacheEntryFake(key) }); var taskResult = task.GetType().GetProperty("Result").GetValue(task); ProjectReflectionShortcuts.SetUpCacheEntryMethod(taskResult.GetType()).Invoke(null, new[] { _mockedCachingService, key, taskResult }); return(task); } //void method if (methodInfo.ReturnType == typeof(void)) { return(null); } //Return default values if (methodInfo.ReturnType.IsGenericType && methodInfo.ReturnType.GetGenericTypeDefinition() == typeof(Task <>)) { var genericArgument = methodInfo.ReturnType.GetGenericArguments().Single(); var defaultValue = genericArgument.GetDefaultValue(); return(CoreReflectionShortcuts.TaskFromResultMethod(genericArgument).Invoke(null, new[] { defaultValue })); } return(methodInfo.ReturnType.GetDefaultValue()); }
internal static IAppCache SetUpCacheEntryRemove <T>(this IAppCache mockedCachingService, string cacheEntryKey) { EnsureArgument.IsNotNull(mockedCachingService, nameof(mockedCachingService)); EnsureArgument.IsNotNullOrEmpty(cacheEntryKey, nameof(cacheEntryKey)); Logger.LogDebug("Setting up cache entry Remove for '{cacheEntryKey}'", cacheEntryKey); Mock.Get(mockedCachingService) .Setup(m => m.Remove(It.Is <string>(s => s.Equals(cacheEntryKey)))) .Callback(() => { Logger.LogDebug("Cache Remove invoked"); ProjectReflectionShortcuts.SetUpCacheEntryGetMethod(typeof(T)).Invoke(null, new object[] { mockedCachingService, cacheEntryKey, default(T) }); }); return(mockedCachingService); }