using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Runtime.CompilerServices; using Moq; using Moq.Language.Flow; using NzbDrone.Common.Composition; using NzbDrone.Common.EnvironmentInfo; using NzbDrone.Test.Common.AutoMoq.Unity; using 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); } if (mock != null) { _container.RegisterInstance(type, mock.Object); } } 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(); } } } private void SetupAutoMoqer(IUnityContainer container) { _container = container; container.RegisterInstance(this); RegisterPlatformLibrary(container); _registeredMocks = new Dictionary(); AddTheAutoMockingContainerExtensionToTheContainer(container); ContainerBuilderBase.RegisterNativeResolver(new[] { "System.Data.SQLite", "Radarr.Core" }); } private static void AddTheAutoMockingContainerExtensionToTheContainer(IUnityContainer container) { container.AddNewExtension(); return; } private Mock TheRegisteredMockForThisType(Type type) where T : class { return (Mock)_registeredMocks.First(x => x.Key == type).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); } private void RegisterPlatformLibrary(IUnityContainer container) { var assemblyName = "Radarr.Windows"; if (OsInfo.IsNotWindows) { assemblyName = "Radarr.Mono"; } if (!File.Exists(assemblyName + ".dll")) { return; } Assembly.Load(assemblyName); } } }