diff --git a/Directory.Packages.props b/Directory.Packages.props index e3736af1e..2a6c6033f 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -20,6 +20,7 @@ + @@ -27,7 +28,6 @@ - diff --git a/Tests/Helpers/Testably.Abstractions.TestHelpers/AutoDomainDataAttribute.cs b/Tests/Helpers/Testably.Abstractions.TestHelpers/AutoDomainDataAttribute.cs new file mode 100644 index 000000000..a3f3228b4 --- /dev/null +++ b/Tests/Helpers/Testably.Abstractions.TestHelpers/AutoDomainDataAttribute.cs @@ -0,0 +1,111 @@ +using AutoFixture; +using AutoFixture.Xunit2; +using AutoFixture.AutoNSubstitute; +using System; +using System.Linq; +using System.Collections.Generic; + +namespace Testably.Abstractions.TestHelpers; + +/// +/// Extension of that uses applies domain-specific customizations. +/// +public class AutoDomainDataAttribute : AutoDataAttribute +{ + private Type? _customizeWith; + private readonly FixtureFactory _fixtureFactory; + + /// + /// Extension of that uses applies domain-specific customizations. + /// + public AutoDomainDataAttribute() : this(new FixtureFactory()) + { + } + + private AutoDomainDataAttribute(FixtureFactory fixtureFactory) + : base(fixtureFactory.GetFixtureFactory) + { + _fixtureFactory = fixtureFactory; + } + + /// + /// Adds an additional that is applied for only this test. + /// + public Type? CustomizeWith + { + get + { + return _customizeWith; + } + set + { + _customizeWith = value; + _fixtureFactory.CustomizeWith(value); + } + } + + private sealed class FixtureFactory + { + private ICustomization? _customizeWith; + private static Lazy _domainCustomisation { get; } = new(Initialize); + + public IFixture GetFixtureFactory() + { + var fixture = new Fixture(); + fixture.Customize(new AutoNSubstituteCustomization()); + foreach (var domainCustomization in _domainCustomisation.Value) + { + domainCustomization.Customize(fixture); + } + if (_customizeWith != null) + { + fixture.Customize(_customizeWith); + } + return fixture; + } + + public void CustomizeWith(Type? type) + { + Type customizationInterface = typeof(ICustomization); + if (type != null && + customizationInterface.IsAssignableFrom(type)) + { + try + { + _customizeWith = (ICustomization?)Activator.CreateInstance(type); + } + catch (Exception ex) + { + throw new InvalidOperationException( + $"Could not instantiate customization with '{type.Name}'!", ex); + } + } + } + + private static ICustomization[] Initialize() + { + List domainCustomizations = new(); + Type autoDataCustomizationInterface = typeof(IAutoDataCustomization); + foreach (Type type in AppDomain.CurrentDomain.GetAssemblies() + .SelectMany(a => a.GetTypes()) + .Where(x => x.IsClass) + .Where(autoDataCustomizationInterface.IsAssignableFrom)) + { + try + { + IAutoDataCustomization? domainCustomization = (IAutoDataCustomization?)Activator.CreateInstance(type); + if (domainCustomization != null) + { + domainCustomizations.Add(domainCustomization); + } + } + catch (Exception ex) + { + throw new InvalidOperationException( + $"Could not instantiate auto data customization '{type.Name}'!", ex); + } + } + return domainCustomizations.ToArray(); + } + } +} diff --git a/Tests/Helpers/Testably.Abstractions.TestHelpers/IAutoDataCustomization.cs b/Tests/Helpers/Testably.Abstractions.TestHelpers/IAutoDataCustomization.cs new file mode 100644 index 000000000..72dacba9c --- /dev/null +++ b/Tests/Helpers/Testably.Abstractions.TestHelpers/IAutoDataCustomization.cs @@ -0,0 +1,10 @@ +using AutoFixture; + +namespace Testably.Abstractions.TestHelpers; + +/// +/// Marks customizations of that should always be applied when using the . +/// +public interface IAutoDataCustomization : ICustomization +{ +} diff --git a/Tests/Helpers/Testably.Abstractions.TestHelpers/Testably.Abstractions.TestHelpers.csproj b/Tests/Helpers/Testably.Abstractions.TestHelpers/Testably.Abstractions.TestHelpers.csproj index 5cb82e6dc..701d14815 100644 --- a/Tests/Helpers/Testably.Abstractions.TestHelpers/Testably.Abstractions.TestHelpers.csproj +++ b/Tests/Helpers/Testably.Abstractions.TestHelpers/Testably.Abstractions.TestHelpers.csproj @@ -19,7 +19,8 @@ - + + diff --git a/Tests/Testably.Abstractions.AccessControl.Tests/Internal/AccessControlHelperTests.cs b/Tests/Testably.Abstractions.AccessControl.Tests/Internal/AccessControlHelperTests.cs index 40374666f..d7003e2d4 100644 --- a/Tests/Testably.Abstractions.AccessControl.Tests/Internal/AccessControlHelperTests.cs +++ b/Tests/Testably.Abstractions.AccessControl.Tests/Internal/AccessControlHelperTests.cs @@ -1,16 +1,14 @@ -using NSubstitute; -using System.IO; +using System.IO; using Testably.Abstractions.Helpers; namespace Testably.Abstractions.AccessControl.Tests.Internal; public sealed class AccessControlHelperTests { - [Fact] - public void GetExtensibilityOrThrow_CustomDirectoryInfo_ShouldThrowNotSupportedException() + [Theory] + [AutoDomainData] + public void GetExtensibilityOrThrow_CustomDirectoryInfo_ShouldThrowNotSupportedException(IDirectoryInfo sut) { - IDirectoryInfo? sut = Substitute.For(); - Exception? exception = Record.Exception(() => { sut.GetExtensibilityOrThrow(); @@ -22,11 +20,10 @@ public void GetExtensibilityOrThrow_CustomDirectoryInfo_ShouldThrowNotSupportedE .Contain(sut.GetType().Name); } - [Fact] - public void GetExtensibilityOrThrow_CustomFileInfo_ShouldThrowNotSupportedException() + [Theory] + [AutoDomainData] + public void GetExtensibilityOrThrow_CustomFileInfo_ShouldThrowNotSupportedException(IFileInfo sut) { - IFileInfo? sut = Substitute.For(); - Exception? exception = Record.Exception(() => { sut.GetExtensibilityOrThrow(); @@ -116,5 +113,5 @@ public void ThrowIfMissing_MissingFileInfo_ShouldThrowFileNotFoundException() exception!.Message.Should().Contain($"'{sut.FullName}'"); } - private class CustomFileSystemStream() : FileSystemStream(Null, ".", false); + private sealed class CustomFileSystemStream() : FileSystemStream(Null, ".", false); } diff --git a/Tests/Testably.Abstractions.AccessControl.Tests/Testably.Abstractions.AccessControl.Tests.csproj b/Tests/Testably.Abstractions.AccessControl.Tests/Testably.Abstractions.AccessControl.Tests.csproj index 2b163db76..3791356a6 100644 --- a/Tests/Testably.Abstractions.AccessControl.Tests/Testably.Abstractions.AccessControl.Tests.csproj +++ b/Tests/Testably.Abstractions.AccessControl.Tests/Testably.Abstractions.AccessControl.Tests.csproj @@ -13,7 +13,6 @@ -