private MocksRepository FindRepositoryInOps(RepositoryOperationsBase entryOps, object entryKey)
        {
            if (entryOps.IsUsedOnAllThreads)
            {
                var repo = entryOps.FindRepositoryFromAnyThread(entryKey);
                if (repo != null)
                {
                    if (repo.IsRetired)
                    {
                        entryOps.RetireRepository(entryKey, repo);
                        repo = null;
                    }
                }
                return(repo);
            }
            else
            {
                var repo = entryOps.FindRepository(entryKey);
                if (repo != null)
                {
                    if (repo.IsParentToAnotherRepository || repo.IsRetired)
                    {
                        entryOps.RetireRepository(entryKey, repo);
                        repo = null;
                    }
                }

                return(repo);
            }
        }
Example #2
0
        protected void AddRepositoryOperations(Func <MethodBase, bool> matchesMethod, Func <MethodBase, object> getKey, Func <MethodBase, object, bool> isInheritingContext, bool isLeaf, bool isUsedOnAllThreads)
        {
            if (isInheritingContext == null)
            {
                isInheritingContext = (_, __) => false;
            }

            RepositoryOperationsBase ops = this.CreateRepositoryOperations(getKey, matchesMethod, isLeaf, isUsedOnAllThreads, isInheritingContext);

            this.repoOperations.Add(ops);
        }
        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 RepositoryOperationsBase CreateRepositoryOperations(Func <MethodBase, object> getKey, Func <MethodBase, bool> matchesMethod, bool isLeaf, bool isUsedOnAllThreads, Func <MethodBase, object, bool> isInheritingContext)
        {
            RepositoryOperationsBase repoOperations = null;

            if (Mock.IsProfilerEnabled)
            {
                repoOperations = new RepositoryOperationsStrongRef();
            }
            else
            {
                repoOperations = new RepositoryOperationsWeakRef();
            }

            repoOperations.GetKey              = getKey;
            repoOperations.MatchesMethod       = matchesMethod;
            repoOperations.IsLeaf              = isLeaf;
            repoOperations.IsUsedOnAllThreads  = isUsedOnAllThreads;
            repoOperations.IsInheritingContext = isInheritingContext;

            return(repoOperations);
        }
        public override bool RetireRepository()
        {
            RepositoryOperationsBase entryOps = null;
            int repoIdx;
            var testMethod = FindTestMethod(out repoIdx, out entryOps);

            if (testMethod == null)
            {
                return(false);
            }

            var entryKey = entryOps.GetKey(testMethod);

            MocksRepository repo = FindRepositoryInOps(entryOps, entryKey);

            if (repo != null)
            {
                entryOps.RetireRepository(entryKey, repo);
            }

            return(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)
        {
            MethodBase testMethod = this.GetTestMethod();

            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.");
                }
            }
            else
            {
                testMethod = AsyncContextResolver.GetContext();
            }

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

                JMDebug.Assert(entryOps != null);
            }

            return(testMethod);
        }
        public override MocksRepository ResolveRepository(UnresolvedContextBehavior unresolvedContextBehavior)
        {
            RepositoryOperationsBase entryOps = null;
            int repoIdx;
            var testMethod = FindTestMethod(out repoIdx, out entryOps);

            if (testMethod == null)
            {
                return(null);
            }

            var entryKey = entryOps.GetKey(testMethod);

            MocksRepository repo = FindRepositoryInOps(entryOps, entryKey);

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

            //Check if this is the same kind of method but from a derived class, thus building context.
            MocksRepository parentRepo = entryOps.FindRepositoryToInherit(testMethod);

            if (parentRepo == null)
            {
                for (var repoIdxParent = repoIdx + 1; parentRepo == null && repoIdxParent < this.repoOperations.Count; ++repoIdxParent)
                {
                    var ops = this.repoOperations[repoIdxParent];
                    if (ops.IsLeaf)
                    {
                        continue;
                    }

                    var parentKey = ops.GetKey(testMethod);
                    if (ops.IsUsedOnAllThreads)
                    {
                        parentRepo = ops.FindRepositoryFromAnyThread(parentKey);
                    }
                    else
                    {
                        parentRepo = ops.FindRepository(parentKey) ?? ops.FindRepositoryToInherit(testMethod);
                    }
                }
            }

            MocksRepository entryRepo;

            try
            {
                entryRepo = new MocksRepository(parentRepo, testMethod);
                entryOps.AddRepository(entryKey, entryRepo);
                OnMocksRepositoryCreated(repo);
            }
            catch (TypeInitializationException e)
            {
                throw e.InnerException;
            }

            return(entryRepo);
        }
		private MocksRepository FindRepositoryInOps(RepositoryOperationsBase entryOps, object entryKey)
		{
			if (entryOps.IsUsedOnAllThreads)
			{
				var repo = entryOps.FindRepositoryFromAnyThread(entryKey);
				if (repo != null)
				{
					if (repo.IsRetired)
					{
						entryOps.RetireRepository(entryKey, repo);
						repo = null;
					}
				}
				return repo;
			}
			else
			{
				var repo = entryOps.FindRepository(entryKey);
				if (repo != null)
				{
					if (repo.IsParentToAnotherRepository || repo.IsRetired)
					{
						entryOps.RetireRepository(entryKey, repo);
						repo = null;
					}
				}

				return repo;
			}
		}
		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;
		}