public override MocksRepository ResolveRepository(UnresolvedContextBehavior unresolvedContextBehavior)
        {
            lock (this.repositorySync)
            {
                var testMethod = this.GetTestMethod();
                if (testMethod != null)
                {
                    return(repositories[testMethod.DeclaringType]);
                }

                if (unresolvedContextBehavior == UnresolvedContextBehavior.DoNotCreateNew)
                {
                    return(null);
                }

                var stackTrace     = new StackTrace();
                var frames         = stackTrace.EnumerateFrames().ToList();
                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);
            }
        }
Beispiel #2
0
        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);
        }
Beispiel #3
0
        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
            }

            // mock invocations in static constructors according to the behavior
            if (invocation.InRunClassConstructor)
            {
                return(invocation.InArrange && !invocation.CallOriginal);
            }

            return(invocation.InArrange && !invocation.InArrangeArgMatching || this.type == RecursiveMockingBehaviorType.ReturnMock);
        }
        public override MethodBase GetTestMethod()
        {
            var stackTrace = new StackTrace();
            var frames     = stackTrace.EnumerateFrames().ToList();
            var testMethod = this.FindExistingTestMethod(frames);

            return(testMethod);
        }
Beispiel #5
0
        public static void RetireRepository()
        {
            var stackTrace = new StackTrace();

            if (stackTrace.EnumerateFrames().Contains(contextMethod))
            {
                contextRepository.Retire();

                contextMethod     = null;
                contextRepository = null;
            }
        }
        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);
        }
        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 MethodBase GetTestMethod()
        {
            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)
            {
                string 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);
            }

            MethodBase testMethod = allTestMethods.FirstOrDefault();

            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 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);
        }
        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;
        }