public static MocksRepository ResolveRepository(UnresolvedContextBehavior unresolvedContextBehavior) { var stackTrace = new StackTrace(); MethodBase callingMethodOutsideJustmock = null; foreach (var method in stackTrace.EnumerateFrames()) { if (contextMethod == method) return contextRepository; if (callingMethodOutsideJustmock == null && method.Module.Assembly != typeof(MocksRepository).Assembly) callingMethodOutsideJustmock = method; } if (callingMethodOutsideJustmock != null && unresolvedContextBehavior == UnresolvedContextBehavior.CreateNewContextualOrLocal) { // don't reset the old repository - because the mocks created from it may still be used, e.g. if the method // associated with ResolveRepository works as a factory for mocks which are then exercised elsewhere contextMethod = callingMethodOutsideJustmock; contextRepository = new MocksRepository(null, contextMethod); return contextRepository; } return null; }
public static void RetireRepository() { var stackTrace = new StackTrace(); if (stackTrace.EnumerateFrames().Contains(contextMethod)) { contextRepository.Retire(); contextMethod = null; contextRepository = null; } }
public override bool RetireRepository() { var stackTrace = new StackTrace(); var testMethod = FindExistingTestMethod(stackTrace.EnumerateFrames()); if (testMethod == null) return false; var key = testMethod.DeclaringType; var repo = repositories[key]; repositories.Remove(key); repo.Retire(); return true; }
public override MocksRepository ResolveRepository(UnresolvedContextBehavior unresolvedContextBehavior) { var stackTrace = new StackTrace(); var frames = stackTrace.EnumerateFrames().ToList(); var testMethod = FindExistingTestMethod(frames); if (testMethod != null) return repositories[testMethod.DeclaringType]; if (unresolvedContextBehavior == UnresolvedContextBehavior.DoNotCreateNew) return null; var caller = frames.FirstOrDefault(method => method.Module.Assembly != typeof(MocksRepository).Assembly); var mspecTestClass = caller.DeclaringType; MocksRepository parentRepo; repositories.TryGetValue(mspecTestClass.BaseType, out parentRepo); var repo = new MocksRepository(parentRepo, caller); repositories.Add(mspecTestClass, repo); return repo; }
public void Process(Invocation invocation) { if (invocation.IsReturnValueSet) return; var returnType = invocation.Method.GetReturnType(); if (returnType == typeof(void) || returnType.IsValueType) return; if (invocation.Method.Name == "ToString" && invocation.Method.GetParameters().Length == 0 && invocation.UserProvidedImplementation) return; object mock = null; List<KeyValuePair<object, object>> mocksList; if (mocks.TryGetValue(invocation.Method, out mocksList)) { // can't put the key part in a Dictionary, // because we can't be sure that GetHashCode() works mock = mocksList.FirstOrDefault(kvp => Equals(kvp.Key, invocation.Instance)).Value; } if (mock == null) { var parentMock = MocksRepository.GetMockMixinFromInvocation(invocation); var repository = parentMock.Repository; var replicator = parentMock as IMockReplicator; bool mustReturnAMock = invocation.InArrange || this.type == RecursiveMockingBehaviorType.ReturnMock; if (mustReturnAMock || this.type == RecursiveMockingBehaviorType.ReturnDefault) { if (returnType.IsArray) { mock = Array.CreateInstance(returnType.GetElementType(), Enumerable.Repeat(0, returnType.GetArrayRank()).ToArray()); } var idictionaryType = returnType.GetImplementationOfGenericInterface(typeof(IDictionary<,>)); if (mock == null && idictionaryType != null) { var dictType = typeof(Dictionary<,>).MakeGenericType(idictionaryType.GetGenericArguments()); mock = MockCollection.Create(returnType, repository, replicator, (IEnumerable)MockingUtil.CreateInstance(dictType)); } var ienumerableType = returnType.GetImplementationOfGenericInterface(typeof(IEnumerable<>)); if (mock == null && ienumerableType != null) { var listType = typeof(List<>).MakeGenericType(ienumerableType.GetGenericArguments()); mock = MockCollection.Create(returnType, repository, replicator, (IEnumerable)MockingUtil.CreateInstance(listType)); } if (mock == null && mustReturnAMock) { #if !LITE_EDITION var stackTrace = new StackTrace(); var methodCallingArrange = stackTrace.EnumerateFrames() .SkipWhile(m => !Attribute.IsDefined(m, typeof(ArrangeMethodAttribute))) .SkipWhile(m => m.Module.Assembly == typeof(MocksRepository).Assembly) .FirstOrDefault(); if (methodCallingArrange != null && invocation.Method.DeclaringType.IsAssignableFrom(methodCallingArrange.DeclaringType)) return; #endif if (typeof(String) == returnType) { mock = String.Empty; } else { try { mock = replicator.CreateSimilarMock(repository, returnType, null, true, null); } catch (MockException) { } } } } if (mock == null) return; if (mocksList == null) { mocksList = new List<KeyValuePair<object, object>>(); mocks.Add(invocation.Method, mocksList); } mocksList.Add(new KeyValuePair<object, object>(invocation.Instance, mock)); var mockMixin = MocksRepository.GetMockMixin(mock, null); if (parentMock != null && mockMixin != null) parentMock.DependentMocks.Add(mock); } invocation.ReturnValue = mock; invocation.CallOriginal = false; invocation.UserProvidedImplementation = true; }
private MethodBase FindTestMethod(out int repoIdx, out RepositoryOperationsBase entryOps) { var stackTrace = new StackTrace(); var q = from method in stackTrace.EnumerateFrames() where repoOperations.Any(repo => repo.MatchesMethod(method)) select method; var testMethod = q.FirstOrDefault(); if (testMethod != null) { var disableAttr = Attribute.GetCustomAttribute(testMethod, typeof(DisableAutomaticRepositoryResetAttribute)) as DisableAutomaticRepositoryResetAttribute; if (disableAttr != null && ProfilerInterceptor.IsProfilerAttached && !disableAttr.AllowMocking) throw new MockException("Using the mocking API in a test method decorated with DisableAutomaticRepositoryResetAttribute is unsafe. Read the documentation of the DisableAutomaticRepositoryResetAttribute class for further information and possible solutions."); } repoIdx = 0; entryOps = null; if (testMethod != null) { for (repoIdx = 0; repoIdx < this.repoOperations.Count; ++repoIdx) { var ops = this.repoOperations[repoIdx]; if (ops.MatchesMethod(testMethod)) { entryOps = ops; break; } } Debug.Assert(entryOps != null); } return testMethod; }
private MethodBase FindTestMethod(out int repoIdx, out RepositoryOperationsBase entryOps) { var stackTrace = new StackTrace(); var q = from method in stackTrace.EnumerateFrames() where repoOperations.Any(repo => repo.MatchesMethod(method)) select method; var allTestMethods = q.Distinct().ToArray(); if (allTestMethods.Length > 1) { var message = "Calling one test method from another could result in unexpected behavior and must be avoided. Extract common mocking logic to a non-test method. At:\n" + stackTrace; DebugView.DebugTrace(message); } var testMethod = allTestMethods.FirstOrDefault(); if (testMethod != null) { var disableAttr = Attribute.GetCustomAttribute(testMethod, typeof(DisableAutomaticRepositoryResetAttribute)) as DisableAutomaticRepositoryResetAttribute; if (disableAttr != null && ProfilerInterceptor.IsProfilerAttached && !disableAttr.AllowMocking) throw new MockException("Using the mocking API in a test method decorated with DisableAutomaticRepositoryResetAttribute is unsafe. Read the documentation of the DisableAutomaticRepositoryResetAttribute class for further information and possible solutions."); } repoIdx = 0; entryOps = null; if (testMethod != null) { for (repoIdx = 0; repoIdx < this.repoOperations.Count; ++repoIdx) { var ops = this.repoOperations[repoIdx]; if (ops.MatchesMethod(testMethod)) { entryOps = ops; break; } } Debug.Assert(entryOps != null); } return testMethod; }
private bool MustReturnMock(Invocation invocation, bool checkPropertyOnTestFixture = false) { if (checkPropertyOnTestFixture) { #if !LITE_EDITION var stackTrace = new StackTrace(); var methodCallingArrange = stackTrace.EnumerateFrames() .SkipWhile(m => !Attribute.IsDefined(m, typeof(ArrangeMethodAttribute))) .SkipWhile(m => m.Module.Assembly == typeof(MocksRepository).Assembly) .FirstOrDefault(); if (methodCallingArrange != null && invocation.Method.DeclaringType.IsAssignableFrom(methodCallingArrange.DeclaringType)) return false; #endif } return invocation.InArrange || this.type == RecursiveMockingBehaviorType.ReturnMock; }
public void Process(Invocation invocation) { if (invocation.ReturnValue != null) return; var returnType = invocation.Method.GetReturnType(); if (returnType == typeof(void) || returnType.IsValueType) return; var key = new KeyValuePair<object, MethodBase>(invocation.Instance, invocation.Method); object mock; if (!mocks.TryGetValue(key, out mock)) { var parentMock = MocksRepository.GetMockMixinFromInvocation(invocation); var repository = parentMock.Repository; var replicator = parentMock as IMockReplicator; bool mustReturnAMock = invocation.InArrange || this.type == RecursiveMockingBehaviorType.ReturnMock; if (mustReturnAMock || this.type == RecursiveMockingBehaviorType.ReturnDefault) { if (returnType.IsArray) { mock = Array.CreateInstance(returnType.GetElementType(), Enumerable.Repeat(0, returnType.GetArrayRank()).ToArray()); } var idictionaryType = returnType.GetImplementationOfGenericInterface(typeof(IDictionary<,>)); if (mock == null && idictionaryType != null) { var dictType = typeof(Dictionary<,>).MakeGenericType(idictionaryType.GetGenericArguments()); mock = MockCollection.Create(returnType, repository, replicator, (IEnumerable)MockingUtil.CreateInstance(dictType)); } var ienumerableType = returnType.GetImplementationOfGenericInterface(typeof(IEnumerable<>)); if (mock == null && ienumerableType != null) { var listType = typeof(List<>).MakeGenericType(ienumerableType.GetGenericArguments()); mock = MockCollection.Create(returnType, repository, replicator, (IEnumerable)MockingUtil.CreateInstance(listType)); } if (mock == null && mustReturnAMock) { var stackTrace = new StackTrace(); var methodCallingArrange = stackTrace.EnumerateFrames() .SkipWhile(m => !Attribute.IsDefined(m, typeof(ArrangeMethodAttribute))) .SkipWhile(m => m.Module.Assembly == typeof(MocksRepository).Assembly) .FirstOrDefault(); if (methodCallingArrange != null && invocation.Method.DeclaringType.IsAssignableFrom(methodCallingArrange.DeclaringType)) return; if (typeof(String) == returnType) { mock = String.Empty; } else { try { mock = replicator.CreateSimilarMock(repository, returnType, null, true, null); } catch (MockException ex) { } } } } if (mock == null) return; mocks.Add(key, mock); var mockMixin = MocksRepository.GetMockMixin(mock, null); if (parentMock != null && mockMixin != null) parentMock.DependentMocks.Add(mock); } invocation.ReturnValue = mock; invocation.CallOriginal = false; invocation.UserProvidedImplementation = true; }