diff --git a/test/Api.Test/Api.Test.csproj b/test/Api.Test/Api.Test.csproj index e8c71e9f23..dd902a33d0 100644 --- a/test/Api.Test/Api.Test.csproj +++ b/test/Api.Test/Api.Test.csproj @@ -22,6 +22,7 @@ + diff --git a/test/Api.Test/AutoFixture/ControllerCustomization.cs b/test/Api.Test/AutoFixture/ControllerCustomization.cs new file mode 100644 index 0000000000..137cadb895 --- /dev/null +++ b/test/Api.Test/AutoFixture/ControllerCustomization.cs @@ -0,0 +1,38 @@ +using AutoFixture; +using Microsoft.AspNetCore.Mvc.ModelBinding; +using Microsoft.AspNetCore.Mvc; +using Bit.Api.Controllers; +using AutoFixture.Kernel; +using System; +using Bit.Test.Common.AutoFixture; +using Org.BouncyCastle.Security; + +namespace Bit.Api.Test.AutoFixture +{ + /// + /// Disables setting of Auto Properties on the Controller to avoid ASP.net initialization errors. Still sets constructor dependencies. + /// + /// + public class ControllerCustomization : ICustomization + { + private readonly Type _controllerType; + public ControllerCustomization(Type controllerType) + { + if (!controllerType.IsAssignableTo(typeof(Controller))) + { + throw new InvalidParameterException($"{nameof(controllerType)} must derive from {typeof(Controller).Name}"); + } + + _controllerType = controllerType; + } + + public void Customize(IFixture fixture) + { + fixture.Customizations.Add(new BuilderWithoutAutoProperties(_controllerType)); + } + } + public class ControllerCustomization : ICustomization where T : Controller + { + public void Customize(IFixture fixture) => new ControllerCustomization(typeof(T)).Customize(fixture); + } +} diff --git a/test/Common/AutoFixture/Attributes/BitCustomizeAttribute.cs b/test/Common/AutoFixture/Attributes/BitCustomizeAttribute.cs new file mode 100644 index 0000000000..32910ef537 --- /dev/null +++ b/test/Common/AutoFixture/Attributes/BitCustomizeAttribute.cs @@ -0,0 +1,22 @@ +using System; +using AutoFixture; + +namespace Bit.Test.Common.AutoFixture.Attributes +{ + /// + /// + /// Base class for customizing parameters in methods decorated with the + /// Bit.Test.Common.AutoFixture.Attributes.MemberAutoDataAttribute. + /// + /// ⚠ Warning ⚠ Will not insert customizations into AutoFixture's AutoDataAttribute build chain + /// + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Parameter, AllowMultiple = true)] + public abstract class BitCustomizeAttribute : Attribute + { + /// + /// /// Gets a customization for the method's parameters. + /// + /// A customization for the method's paramters. + public abstract ICustomization GetCustomization(); + } +} diff --git a/test/Common/AutoFixture/BuilderWithoutAutoProperties.cs b/test/Common/AutoFixture/BuilderWithoutAutoProperties.cs new file mode 100644 index 0000000000..81df3206a0 --- /dev/null +++ b/test/Common/AutoFixture/BuilderWithoutAutoProperties.cs @@ -0,0 +1,41 @@ +using System; +using AutoFixture; +using AutoFixture.Dsl; +using AutoFixture.Kernel; + +namespace Bit.Test.Common.AutoFixture +{ + public class BuilderWithoutAutoProperties : ISpecimenBuilder + { + private readonly Type _type; + public BuilderWithoutAutoProperties(Type type) + { + _type = type; + } + + public object Create(object request, ISpecimenContext context) + { + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + + var type = request as Type; + if (type == null || type != _type) + { + return new NoSpecimen(); + } + + var fixture = new Fixture(); + // This is the equivalent of _fixture.Build<_type>().OmitAutoProperties().Create(request, context), but no overload for + // Build(Type type) exists. + dynamic reflectedComposer = typeof(Fixture).GetMethod("Build").MakeGenericMethod(_type).Invoke(fixture, null); + return reflectedComposer.OmitAutoProperties().Create(request, context); + } + } + public class BuilderWithoutAutoProperties : ISpecimenBuilder + { + public object Create(object request, ISpecimenContext context) => + new BuilderWithoutAutoProperties(typeof(T)).Create(request, context); + } +}