using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Linq.Expressions; using System.Runtime.CompilerServices; using Microsoft.Practices.Unity; using Moq; using Moq.Language.Flow; using NzbDrone.Test.Common.AutoMoq.Unity; [assembly: InternalsVisibleTo("AutoMoq.Tests")] namespace NzbDrone.Test.Common.AutoMoq { [DebuggerStepThrough] public class AutoMoqer { public readonly MockBehavior DefaultBehavior = MockBehavior.Default; public Type ResolveType; private IUnityContainer container; private IDictionary registeredMocks; public AutoMoqer() { SetupAutoMoqer(new UnityContainer()); } public AutoMoqer(MockBehavior defaultBehavior) { DefaultBehavior = defaultBehavior; SetupAutoMoqer(new UnityContainer()); } public AutoMoqer(IUnityContainer container) { SetupAutoMoqer(container); } public virtual T Resolve() { ResolveType = typeof(T); var result = container.Resolve(); SetConstant(result); ResolveType = null; return result; } public virtual Mock GetMock() where T : class { return GetMock(DefaultBehavior); } public virtual Mock GetMock(MockBehavior behavior) where T : class { ResolveType = null; var type = GetTheMockType(); if (GetMockHasNotBeenCalledForThisType(type)) { CreateANewMockAndRegisterIt(type, behavior); } var mock = TheRegisteredMockForThisType(type); if (behavior != MockBehavior.Default && mock.Behavior == MockBehavior.Default) { throw new InvalidOperationException("Unable to change be behaviour of a an existing mock."); } return mock; } public virtual void SetMock(Type type, Mock mock) { if (registeredMocks.ContainsKey(type) == false) registeredMocks.Add(type, mock); } public virtual void SetConstant(T instance) { container.RegisterInstance(instance); SetMock(instance.GetType(), null); } public ISetup Setup(Expression> expression) where T : class { return GetMock().Setup(expression); } public ISetup Setup(Expression> expression) where T : class { return GetMock().Setup(expression); } public void Verify(Expression> expression) where T : class { GetMock().Verify(expression); } public void Verify(Expression> expression, string failMessage) where T : class { GetMock().Verify(expression, failMessage); } public void Verify(Expression> expression, Times times) where T : class { GetMock().Verify(expression, times); } public void Verify(Expression> expression, Times times, string failMessage) where T : class { GetMock().Verify(expression, times, failMessage); } public void VerifyAllMocks() { foreach (var registeredMock in registeredMocks) { var mock = registeredMock.Value as Mock; if (mock != null) mock.VerifyAll(); } } #region private methods private void SetupAutoMoqer(IUnityContainer container) { this.container = container; container.RegisterInstance(this); registeredMocks = new Dictionary(); AddTheAutoMockingContainerExtensionToTheContainer(container); } private static void AddTheAutoMockingContainerExtensionToTheContainer(IUnityContainer container) { container.AddNewExtension(); return; } private Mock TheRegisteredMockForThisType(Type type) where T : class { return (Mock)registeredMocks.Where(x => x.Key == type).First().Value; } private void CreateANewMockAndRegisterIt(Type type, MockBehavior behavior) where T : class { var mock = new Mock(behavior); container.RegisterInstance(mock.Object); SetMock(type, mock); } private bool GetMockHasNotBeenCalledForThisType(Type type) { return registeredMocks.ContainsKey(type) == false; } private static Type GetTheMockType() where T : class { return typeof(T); } #endregion } }