diff --git a/src/NzbDrone.Common.Test/DiskTests/DiskProviderFixtureBase.cs b/src/NzbDrone.Common.Test/DiskTests/DiskProviderFixtureBase.cs index 617cba13a6..c586f85b48 100644 --- a/src/NzbDrone.Common.Test/DiskTests/DiskProviderFixtureBase.cs +++ b/src/NzbDrone.Common.Test/DiskTests/DiskProviderFixtureBase.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using System.IO.Abstractions; using FluentAssertions; using NUnit.Framework; using NzbDrone.Common.Disk; @@ -10,6 +11,12 @@ namespace NzbDrone.Common.Test.DiskTests public abstract class DiskProviderFixtureBase : TestBase where TSubject : class, IDiskProvider { + [SetUp] + public void BaseSetup() + { + Mocker.SetConstant(new FileSystem()); + } + [Test] public void writealltext_should_truncate_existing() { diff --git a/src/NzbDrone.Common.Test/DiskTests/FreeSpaceFixtureBase.cs b/src/NzbDrone.Common.Test/DiskTests/FreeSpaceFixtureBase.cs index 2b4d356cd5..32957f3317 100644 --- a/src/NzbDrone.Common.Test/DiskTests/FreeSpaceFixtureBase.cs +++ b/src/NzbDrone.Common.Test/DiskTests/FreeSpaceFixtureBase.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using System.IO.Abstractions; using FluentAssertions; using NUnit.Framework; using NzbDrone.Common.Disk; @@ -10,6 +11,12 @@ namespace NzbDrone.Common.Test.DiskTests public abstract class FreeSpaceFixtureBase : TestBase where TSubject : class, IDiskProvider { + [SetUp] + public void BaseSetup() + { + Mocker.SetConstant(new FileSystem()); + } + [Test] public void should_get_free_space_for_folder() { diff --git a/src/NzbDrone.Core.Test/Framework/FileSystemTest.cs b/src/NzbDrone.Core.Test/Framework/FileSystemTest.cs index 8790355c95..52b98284f8 100644 --- a/src/NzbDrone.Core.Test/Framework/FileSystemTest.cs +++ b/src/NzbDrone.Core.Test/Framework/FileSystemTest.cs @@ -1,7 +1,8 @@ -using System.IO.Abstractions.TestingHelpers; +using System.IO.Abstractions; +using System.IO.Abstractions.TestingHelpers; using NUnit.Framework; using NzbDrone.Common.Disk; -using Unity.Resolution; +using NzbDrone.Test.Common.AutoMoq; namespace NzbDrone.Core.Test.Framework { @@ -14,12 +15,9 @@ public abstract class FileSystemTest : CoreTest [SetUp] public void FileSystemTestSetup() { - FileSystem = new MockFileSystem(); + FileSystem = (MockFileSystem)Mocker.Resolve(FileSystemType.Mock); - DiskProvider = Mocker.Resolve("ActualDiskProvider", new ResolverOverride[] - { - new ParameterOverride("fileSystem", FileSystem) - }); + DiskProvider = Mocker.Resolve(FileSystemType.Mock); } } } diff --git a/src/NzbDrone.Core.Test/MediaCoverTests/MediaCoverServiceFixture.cs b/src/NzbDrone.Core.Test/MediaCoverTests/MediaCoverServiceFixture.cs index 38ffd84366..c4a9d59f25 100644 --- a/src/NzbDrone.Core.Test/MediaCoverTests/MediaCoverServiceFixture.cs +++ b/src/NzbDrone.Core.Test/MediaCoverTests/MediaCoverServiceFixture.cs @@ -1,5 +1,7 @@ using System; using System.Collections.Generic; +using System.IO; +using System.IO.Abstractions; using System.Linq; using FizzWare.NBuilder; using FluentAssertions; @@ -126,6 +128,13 @@ public void should_convert_media_urls_to_local_without_time_if_file_doesnt_exist } }; + var path = Path.Combine(TestContext.CurrentContext.TestDirectory, "Files", "Media", "NonExistant.mp4"); + var fileInfo = new FileInfo(path); + + Mocker.GetMock() + .Setup(c => c.GetFileInfo(It.IsAny())) + .Returns((FileInfoBase)fileInfo); + Subject.ConvertToLocalUrls(12, MediaCoverEntity.Artist, covers); covers.Single().Url.Should().Be("/MediaCover/12/banner" + extension); diff --git a/src/NzbDrone.Core.Test/MediaFiles/AudioTagServiceFixture.cs b/src/NzbDrone.Core.Test/MediaFiles/AudioTagServiceFixture.cs index b461298f45..04c3525bc9 100644 --- a/src/NzbDrone.Core.Test/MediaFiles/AudioTagServiceFixture.cs +++ b/src/NzbDrone.Core.Test/MediaFiles/AudioTagServiceFixture.cs @@ -13,6 +13,7 @@ using NzbDrone.Core.Music; using NzbDrone.Core.Test.Framework; using NzbDrone.Test.Common; +using NzbDrone.Test.Common.AutoMoq; namespace NzbDrone.Core.Test.MediaFiles.AudioTagServiceFixture { @@ -55,9 +56,7 @@ public static IEnumerable TestCases [SetUp] public void Setup() { - _diskProvider = Mocker.Resolve("ActualDiskProvider"); - - Mocker.SetConstant(_diskProvider); + _diskProvider = Mocker.Resolve(FileSystemType.Actual); Mocker.GetMock() .Setup(x => x.WriteAudioTags) diff --git a/src/NzbDrone.Mono.Test/EnvironmentInfo/ReleaseFileVersionAdapterFixture.cs b/src/NzbDrone.Mono.Test/EnvironmentInfo/ReleaseFileVersionAdapterFixture.cs index d33abb147b..136b55b265 100644 --- a/src/NzbDrone.Mono.Test/EnvironmentInfo/ReleaseFileVersionAdapterFixture.cs +++ b/src/NzbDrone.Mono.Test/EnvironmentInfo/ReleaseFileVersionAdapterFixture.cs @@ -1,4 +1,5 @@ -using FluentAssertions; +using System.IO.Abstractions; +using FluentAssertions; using NUnit.Framework; using NzbDrone.Common.Disk; using NzbDrone.Mono.Disk; @@ -16,6 +17,7 @@ public void Setup() { NotBsd(); + Mocker.SetConstant(new FileSystem()); Mocker.SetConstant(Mocker.Resolve()); } diff --git a/src/NzbDrone.Mono.Test/EnvironmentInfo/VersionAdapters/ReleaseFileVersionAdapterFixture.cs b/src/NzbDrone.Mono.Test/EnvironmentInfo/VersionAdapters/ReleaseFileVersionAdapterFixture.cs index 5d27ebd13d..9edb99fe3d 100644 --- a/src/NzbDrone.Mono.Test/EnvironmentInfo/VersionAdapters/ReleaseFileVersionAdapterFixture.cs +++ b/src/NzbDrone.Mono.Test/EnvironmentInfo/VersionAdapters/ReleaseFileVersionAdapterFixture.cs @@ -1,4 +1,5 @@ -using System.IO; +using System.IO; +using System.IO.Abstractions; using FluentAssertions; using Moq; using NUnit.Framework; @@ -20,6 +21,7 @@ public void should_get_version_info_from_actual_linux() { NotBsd(); + Mocker.SetConstant(new FileSystem()); Mocker.SetConstant(Mocker.Resolve()); var info = Subject.Read(); info.FullName.Should().NotBeNullOrWhiteSpace(); diff --git a/src/NzbDrone.Test.Common/AutoMoq/AutoMoqer.cs b/src/NzbDrone.Test.Common/AutoMoq/AutoMoqer.cs index 374a9f9849..8974296a53 100644 --- a/src/NzbDrone.Test.Common/AutoMoq/AutoMoqer.cs +++ b/src/NzbDrone.Test.Common/AutoMoq/AutoMoqer.cs @@ -2,20 +2,14 @@ using System.Collections.Generic; using System.Diagnostics; using System.IO.Abstractions; +using System.IO.Abstractions.TestingHelpers; using System.Linq; -using System.Linq.Expressions; using System.Reflection; -using System.Runtime.CompilerServices; +using DryIoc; using Moq; -using Moq.Language.Flow; using NzbDrone.Common.Composition; using NzbDrone.Common.Disk; using NzbDrone.Common.EnvironmentInfo; -using NzbDrone.Test.Common.AutoMoq.Unity; -using Unity; -using Unity.Resolution; - -[assembly: InternalsVisibleTo("AutoMoq.Tests")] namespace NzbDrone.Test.Common.AutoMoq { @@ -23,41 +17,29 @@ namespace NzbDrone.Test.Common.AutoMoq public class AutoMoqer { public readonly MockBehavior DefaultBehavior = MockBehavior.Default; - public Type ResolveType; - private IUnityContainer _container; - private IDictionary _registeredMocks; + private readonly IContainer _container; + private readonly IDictionary _registeredMocks = new Dictionary(); public AutoMoqer() { - SetupAutoMoqer(new UnityContainer()); - } + _container = CreateTestContainer(new Container(rules => rules.WithMicrosoftDependencyInjectionRules().WithDefaultReuse(Reuse.Singleton))); - public AutoMoqer(MockBehavior defaultBehavior) - { - DefaultBehavior = defaultBehavior; - SetupAutoMoqer(new UnityContainer()); - } + LoadPlatformLibrary(); - public AutoMoqer(IUnityContainer container) - { - SetupAutoMoqer(container); + AssemblyLoader.RegisterSQLiteResolver(); } public virtual T Resolve() { - ResolveType = typeof(T); var result = _container.Resolve(); SetConstant(result); - ResolveType = null; return result; } - public virtual T Resolve(string name, params ResolverOverride[] resolverOverrides) + public virtual T Resolve(object serviceKey) { - ResolveType = typeof(T); - var result = _container.Resolve(name, resolverOverrides); + var result = _container.Resolve(serviceKey: serviceKey); SetConstant(result); - ResolveType = null; return result; } @@ -70,8 +52,7 @@ public virtual Mock GetMock() public virtual Mock GetMock(MockBehavior behavior) where T : class { - ResolveType = null; - var type = GetTheMockType(); + var type = typeof(T); if (GetMockHasNotBeenCalledForThisType(type)) { CreateANewMockAndRegisterIt(type, behavior); @@ -89,88 +70,61 @@ public virtual Mock GetMock(MockBehavior behavior) public virtual void SetMock(Type type, Mock mock) { - if (_registeredMocks.ContainsKey(type) == false) + if (GetMockHasNotBeenCalledForThisType(type)) { _registeredMocks.Add(type, mock); } if (mock != null) { - _container.RegisterInstance(type, mock.Object); + _container.RegisterInstance(type, mock.Object, ifAlreadyRegistered: IfAlreadyRegistered.Replace); } } public virtual void SetConstant(T instance) { - _container.RegisterInstance(instance); + _container.RegisterInstance(instance, ifAlreadyRegistered: IfAlreadyRegistered.Replace); SetMock(instance.GetType(), null); } - public ISetup Setup(Expression> expression) - where T : class + private IContainer CreateTestContainer(IContainer container) { - return GetMock().Setup(expression); - } + var c = container.CreateChild(IfAlreadyRegistered.Replace, + container.Rules + .WithDynamicRegistration((serviceType, serviceKey) => + { + // ignore services with non-default key + if (serviceKey != null) + { + return null; + } - public ISetup Setup(Expression> expression) - where T : class - { - return GetMock().Setup(expression); - } + if (serviceType == typeof(object)) + { + return null; + } - public void Verify(Expression> expression) - where T : class - { - GetMock().Verify(expression); - } + if (serviceType.IsGenericType && serviceType.IsOpenGeneric()) + { + return null; + } - public void Verify(Expression> expression, string failMessage) - where T : class - { - GetMock().Verify(expression, failMessage); - } + // get the Mock object for the abstract class or interface + if (serviceType.IsInterface || serviceType.IsAbstract) + { + return new[] { new DynamicRegistration(GetMockFactory(serviceType), IfAlreadyRegistered.Keep) }; + } - public void Verify(Expression> expression, Times times) - where T : class - { - GetMock().Verify(expression, times); - } + // concrete types + var concreteTypeFactory = serviceType.ToFactory(Reuse.Singleton, FactoryMethod.ConstructorWithResolvableArgumentsIncludingNonPublic); - 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); + return new[] { new DynamicRegistration(concreteTypeFactory) }; + }, + DynamicRegistrationFlags.Service | DynamicRegistrationFlags.AsFallback)); - _registeredMocks = new Dictionary(); + c.Register(typeof(Mock<>), Reuse.Singleton, FactoryMethod.DefaultConstructor()); - RegisterPlatformLibrary(container); - AddTheAutoMockingContainerExtensionToTheContainer(container); - - AssemblyLoader.RegisterSQLiteResolver(); - } - - private static void AddTheAutoMockingContainerExtensionToTheContainer(IUnityContainer container) - { - container.AddNewExtension(); - return; + return c; } private Mock TheRegisteredMockForThisType(Type type) @@ -189,16 +143,21 @@ private void CreateANewMockAndRegisterIt(Type type, MockBehavior behavior) private bool GetMockHasNotBeenCalledForThisType(Type type) { - return _registeredMocks.ContainsKey(type) == false; + return !_registeredMocks.ContainsKey(type); } - private static Type GetTheMockType() - where T : class + private DelegateFactory GetMockFactory(Type serviceType) { - return typeof(T); + var mockType = typeof(Mock<>).MakeGenericType(serviceType); + return new DelegateFactory(r => + { + var mock = (Mock)r.Resolve(mockType); + SetMock(serviceType, mock); + return mock.Object; + }, Reuse.Singleton); } - private void RegisterPlatformLibrary(IUnityContainer container) + private void LoadPlatformLibrary() { var assemblyName = "Lidarr.Windows"; @@ -208,20 +167,25 @@ private void RegisterPlatformLibrary(IUnityContainer container) } var types = Assembly.Load(assemblyName).GetTypes(); - - // This allows us to resolve the platform specific disk provider in FileSystemTest - var diskProvider = types.Where(x => x.Name == "DiskProvider").SingleOrDefault(); - container.RegisterType(typeof(IDiskProvider), diskProvider, "ActualDiskProvider"); - - // This seems to be required now so that Unity can resolve the extra arguments to the - // Mono DiskProvider. I don't understand why we need this now but didn't before. - // It's auto registering everything in the assembly with Ixxx -> xxx. - types.Except(new[] { diskProvider }).Where(t => t.GetInterfaces().Any(i => i.Name == "I" + t.Name)).ToList() - .ForEach(t => container.RegisterType(t.GetInterface("I" + t.Name, false), t)); - - // This tells the mocker to resolve IFileSystem using an actual filesystem (and not a mock) - // if not specified, giving the old behaviour before we switched to System.IO.Abstractions. - SetConstant(new FileSystem()); + var diskProvider = types.SingleOrDefault(x => x.Name == "DiskProvider"); + + // The standard dynamic mock registrations, explicit so DryIoC doesn't get confused when we add alternatives + _container.Register(typeof(IFileSystem), GetMockFactory(typeof(IFileSystem))); + _container.Register(typeof(IDiskProvider), GetMockFactory(typeof(IDiskProvider))); + + // A concrete registration from the platform library using a mock filesystem + _container.RegisterInstance(new MockFileSystem(), serviceKey: FileSystemType.Mock); + _container.Register(typeof(IDiskProvider), + diskProvider, + made: Parameters.Of.Type(serviceKey: FileSystemType.Mock), + serviceKey: FileSystemType.Mock); + + // A concrete registration from the platform library using the actual filesystem + _container.Register(serviceKey: FileSystemType.Actual); + _container.Register(typeof(IDiskProvider), + diskProvider, + made: Parameters.Of.Type(serviceKey: FileSystemType.Actual), + serviceKey: FileSystemType.Actual); } } } diff --git a/src/NzbDrone.Test.Common/AutoMoq/FileSystemType.cs b/src/NzbDrone.Test.Common/AutoMoq/FileSystemType.cs new file mode 100644 index 0000000000..baaa6f4fc5 --- /dev/null +++ b/src/NzbDrone.Test.Common/AutoMoq/FileSystemType.cs @@ -0,0 +1,8 @@ +namespace NzbDrone.Test.Common.AutoMoq +{ + public enum FileSystemType + { + Actual, + Mock + } +} diff --git a/src/NzbDrone.Test.Common/AutoMoq/Unity/AutoMockingBuilderStrategy.cs b/src/NzbDrone.Test.Common/AutoMoq/Unity/AutoMockingBuilderStrategy.cs deleted file mode 100644 index c841dc7d7b..0000000000 --- a/src/NzbDrone.Test.Common/AutoMoq/Unity/AutoMockingBuilderStrategy.cs +++ /dev/null @@ -1,80 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using Moq; -using Unity; -using Unity.Builder; -using Unity.Strategies; - -namespace NzbDrone.Test.Common.AutoMoq.Unity -{ - public class AutoMockingBuilderStrategy : BuilderStrategy - { - private readonly IUnityContainer _container; - private readonly MockRepository _mockFactory; - private readonly IEnumerable _registeredTypes; - - public AutoMockingBuilderStrategy(IEnumerable registeredTypes, IUnityContainer container) - { - var autoMoqer = container.Resolve(); - _mockFactory = new MockRepository(autoMoqer.DefaultBehavior); - _registeredTypes = registeredTypes; - _container = container; - } - - public override void PreBuildUp(ref BuilderContext context) - { - var autoMoqer = _container.Resolve(); - - var type = GetTheTypeFromTheBuilderContext(context); - if (AMockObjectShouldBeCreatedForThisType(type)) - { - var mock = CreateAMockObject(type); - context.Existing = mock.Object; - autoMoqer.SetMock(type, mock); - } - } - - private bool AMockObjectShouldBeCreatedForThisType(Type type) - { - var mocker = _container.Resolve(); - return TypeIsNotRegistered(type) && (mocker.ResolveType == null || mocker.ResolveType != type); - } - - private static Type GetTheTypeFromTheBuilderContext(BuilderContext context) - { - // return (context.OriginalBuildKey).Type; - return context.Type; - } - - private bool TypeIsNotRegistered(Type type) - { - return _registeredTypes.Any(x => x.Equals(type)) == false; - } - - private Mock CreateAMockObject(Type type) - { - var createMethod = GenerateAnInterfaceMockCreationMethod(type); - - return InvokeTheMockCreationMethod(createMethod); - } - - private Mock InvokeTheMockCreationMethod(MethodInfo createMethod) - { - return (Mock)createMethod.Invoke(_mockFactory, new object[] { new List().ToArray() }); - } - - private MethodInfo GenerateAnInterfaceMockCreationMethod(Type type) - { - var createMethodWithNoParameters = _mockFactory.GetType().GetMethod("Create", EmptyArgumentList()); - - return createMethodWithNoParameters.MakeGenericMethod(new[] { type }); - } - - private static Type[] EmptyArgumentList() - { - return new[] { typeof(object[]) }; - } - } -} diff --git a/src/NzbDrone.Test.Common/AutoMoq/Unity/AutoMockingContainerExtension.cs b/src/NzbDrone.Test.Common/AutoMoq/Unity/AutoMockingContainerExtension.cs deleted file mode 100644 index 71838c545f..0000000000 --- a/src/NzbDrone.Test.Common/AutoMoq/Unity/AutoMockingContainerExtension.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System; -using System.Collections.Generic; -using Unity.Builder; -using Unity.Extension; - -namespace NzbDrone.Test.Common.AutoMoq.Unity -{ - public class AutoMockingContainerExtension : UnityContainerExtension - { - private readonly IList _registeredTypes = new List(); - - protected override void Initialize() - { - SetEventsOnContainerToTrackAllRegisteredTypes(); - SetBuildingStrategyForBuildingUnregisteredTypes(); - } - - private void SetEventsOnContainerToTrackAllRegisteredTypes() - { - Context.Registering += (sender, e) => RegisterType(e.TypeFrom); - Context.RegisteringInstance += (sender, e) => RegisterType(e.RegisteredType); - } - - private void RegisterType(Type typeToRegister) - { - _registeredTypes.Add(typeToRegister); - } - - private void SetBuildingStrategyForBuildingUnregisteredTypes() - { - var strategy = new AutoMockingBuilderStrategy(_registeredTypes, Container); - Context.Strategies.Add(strategy, UnityBuildStage.PreCreation); - } - } -} diff --git a/src/NzbDrone.Test.Common/Lidarr.Test.Common.csproj b/src/NzbDrone.Test.Common/Lidarr.Test.Common.csproj index 9be6eaed9e..9204094d70 100644 --- a/src/NzbDrone.Test.Common/Lidarr.Test.Common.csproj +++ b/src/NzbDrone.Test.Common/Lidarr.Test.Common.csproj @@ -10,9 +10,9 @@ - + - +