1
0
mirror of https://github.com/bitwarden/server.git synced 2025-06-30 07:36:14 -05:00

Revert filescoped (#2227)

* Revert "Add git blame entry (#2226)"

This reverts commit 239286737d.

* Revert "Turn on file scoped namespaces (#2225)"

This reverts commit 34fb4cca2a.
This commit is contained in:
Justin Baur
2022-08-29 15:53:48 -04:00
committed by GitHub
parent 239286737d
commit bae03feffe
1208 changed files with 74317 additions and 73126 deletions

View File

@ -3,25 +3,26 @@ using AutoFixture;
using Bit.Test.Common.Helpers;
using Xunit.Sdk;
namespace Bit.Test.Common.AutoFixture.Attributes;
[DataDiscoverer("AutoFixture.Xunit2.NoPreDiscoveryDataDiscoverer", "AutoFixture.Xunit2")]
public class BitAutoDataAttribute : DataAttribute
namespace Bit.Test.Common.AutoFixture.Attributes
{
private readonly Func<IFixture> _createFixture;
private readonly object[] _fixedTestParameters;
public BitAutoDataAttribute(params object[] fixedTestParameters) :
this(() => new Fixture(), fixedTestParameters)
{ }
public BitAutoDataAttribute(Func<IFixture> createFixture, params object[] fixedTestParameters) :
base()
[DataDiscoverer("AutoFixture.Xunit2.NoPreDiscoveryDataDiscoverer", "AutoFixture.Xunit2")]
public class BitAutoDataAttribute : DataAttribute
{
_createFixture = createFixture;
_fixedTestParameters = fixedTestParameters;
}
private readonly Func<IFixture> _createFixture;
private readonly object[] _fixedTestParameters;
public override IEnumerable<object[]> GetData(MethodInfo testMethod)
=> BitAutoDataAttributeHelpers.GetData(testMethod, _createFixture(), _fixedTestParameters);
public BitAutoDataAttribute(params object[] fixedTestParameters) :
this(() => new Fixture(), fixedTestParameters)
{ }
public BitAutoDataAttribute(Func<IFixture> createFixture, params object[] fixedTestParameters) :
base()
{
_createFixture = createFixture;
_fixedTestParameters = fixedTestParameters;
}
public override IEnumerable<object[]> GetData(MethodInfo testMethod)
=> BitAutoDataAttributeHelpers.GetData(testMethod, _createFixture(), _fixedTestParameters);
}
}

View File

@ -1,20 +1,21 @@
using AutoFixture;
namespace Bit.Test.Common.AutoFixture.Attributes;
/// <summary>
/// <para>
/// Base class for customizing parameters in methods decorated with the
/// Bit.Test.Common.AutoFixture.Attributes.MemberAutoDataAttribute.
/// </para>
/// ⚠ Warning ⚠ Will not insert customizations into AutoFixture's AutoDataAttribute build chain
/// </summary>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Parameter, AllowMultiple = true)]
public abstract class BitCustomizeAttribute : Attribute
namespace Bit.Test.Common.AutoFixture.Attributes
{
/// <summary>
/// /// Gets a customization for the method's parameters.
/// <para>
/// Base class for customizing parameters in methods decorated with the
/// Bit.Test.Common.AutoFixture.Attributes.MemberAutoDataAttribute.
/// </para>
/// ⚠ Warning ⚠ Will not insert customizations into AutoFixture's AutoDataAttribute build chain
/// </summary>
/// <returns>A customization for the method's paramters.</returns>
public abstract ICustomization GetCustomization();
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Parameter, AllowMultiple = true)]
public abstract class BitCustomizeAttribute : Attribute
{
/// <summary>
/// /// Gets a customization for the method's parameters.
/// </summary>
/// <returns>A customization for the method's paramters.</returns>
public abstract ICustomization GetCustomization();
}
}

View File

@ -3,22 +3,23 @@ using AutoFixture;
using Bit.Test.Common.Helpers;
using Xunit;
namespace Bit.Test.Common.AutoFixture.Attributes;
public class BitMemberAutoDataAttribute : MemberDataAttributeBase
namespace Bit.Test.Common.AutoFixture.Attributes
{
private readonly Func<IFixture> _createFixture;
public BitMemberAutoDataAttribute(string memberName, params object[] parameters) :
this(() => new Fixture(), memberName, parameters)
{ }
public BitMemberAutoDataAttribute(Func<IFixture> createFixture, string memberName, params object[] parameters) :
base(memberName, parameters)
public class BitMemberAutoDataAttribute : MemberDataAttributeBase
{
_createFixture = createFixture;
}
private readonly Func<IFixture> _createFixture;
protected override object[] ConvertDataItem(MethodInfo testMethod, object item) =>
BitAutoDataAttributeHelpers.GetData(testMethod, _createFixture(), item as object[]).First();
public BitMemberAutoDataAttribute(string memberName, params object[] parameters) :
this(() => new Fixture(), memberName, parameters)
{ }
public BitMemberAutoDataAttribute(Func<IFixture> createFixture, string memberName, params object[] parameters) :
base(memberName, parameters)
{
_createFixture = createFixture;
}
protected override object[] ConvertDataItem(MethodInfo testMethod, object item) =>
BitAutoDataAttributeHelpers.GetData(testMethod, _createFixture(), item as object[]).First();
}
}

View File

@ -1,22 +1,23 @@
using AutoFixture;
namespace Bit.Test.Common.AutoFixture.Attributes;
/// <summary>
/// Disables setting of Auto Properties on the Controller to avoid ASP.net initialization errors from a mock environment. Still sets constructor dependencies.
/// </summary>
public class ControllerCustomizeAttribute : BitCustomizeAttribute
namespace Bit.Test.Common.AutoFixture.Attributes
{
private readonly Type _controllerType;
/// <summary>
/// Initialize an instance of the ControllerCustomizeAttribute class
/// Disables setting of Auto Properties on the Controller to avoid ASP.net initialization errors from a mock environment. Still sets constructor dependencies.
/// </summary>
/// <param name="controllerType">The Type of the controller to allow autofixture to create</param>
public ControllerCustomizeAttribute(Type controllerType)
public class ControllerCustomizeAttribute : BitCustomizeAttribute
{
_controllerType = controllerType;
}
private readonly Type _controllerType;
public override ICustomization GetCustomization() => new ControllerCustomization(_controllerType);
/// <summary>
/// Initialize an instance of the ControllerCustomizeAttribute class
/// </summary>
/// <param name="controllerType">The Type of the controller to allow autofixture to create</param>
public ControllerCustomizeAttribute(Type controllerType)
{
_controllerType = controllerType;
}
public override ICustomization GetCustomization() => new ControllerCustomization(_controllerType);
}
}

View File

@ -1,22 +1,23 @@
using AutoFixture;
using AutoFixture.Xunit2;
namespace Bit.Test.Common.AutoFixture.Attributes;
public class CustomAutoDataAttribute : AutoDataAttribute
namespace Bit.Test.Common.AutoFixture.Attributes
{
public CustomAutoDataAttribute(params Type[] iCustomizationTypes) : this(iCustomizationTypes
.Select(t => (ICustomization)Activator.CreateInstance(t)).ToArray())
{ }
public CustomAutoDataAttribute(params ICustomization[] customizations) : base(() =>
public class CustomAutoDataAttribute : AutoDataAttribute
{
var fixture = new Fixture();
foreach (var customization in customizations)
public CustomAutoDataAttribute(params Type[] iCustomizationTypes) : this(iCustomizationTypes
.Select(t => (ICustomization)Activator.CreateInstance(t)).ToArray())
{ }
public CustomAutoDataAttribute(params ICustomization[] customizations) : base(() =>
{
fixture.Customize(customization);
}
return fixture;
})
{ }
var fixture = new Fixture();
foreach (var customization in customizations)
{
fixture.Customize(customization);
}
return fixture;
})
{ }
}
}

View File

@ -1,42 +1,43 @@
using System.Reflection;
using Xunit.Sdk;
namespace Bit.Test.Common.AutoFixture.Attributes;
/// <summary>
/// Used for collecting data from environment useful for when we want to test an integration with another service and
/// it might require an api key or other piece of sensitive data that we don't want slipping into the wrong hands.
/// </summary>
/// <remarks>
/// It probably should be refactored to support fixtures and other customization so it can more easily be used in conjunction
/// with more parameters. Currently it attempt to match environment variable names to values of the parameter type in that positions.
/// It will start from the first parameter and go for each supplied name.
/// </remarks>
public class EnvironmentDataAttribute : DataAttribute
namespace Bit.Test.Common.AutoFixture.Attributes
{
private readonly string[] _environmentVariableNames;
public EnvironmentDataAttribute(params string[] environmentVariableNames)
/// <summary>
/// Used for collecting data from environment useful for when we want to test an integration with another service and
/// it might require an api key or other piece of sensitive data that we don't want slipping into the wrong hands.
/// </summary>
/// <remarks>
/// It probably should be refactored to support fixtures and other customization so it can more easily be used in conjunction
/// with more parameters. Currently it attempt to match environment variable names to values of the parameter type in that positions.
/// It will start from the first parameter and go for each supplied name.
/// </remarks>
public class EnvironmentDataAttribute : DataAttribute
{
_environmentVariableNames = environmentVariableNames;
}
private readonly string[] _environmentVariableNames;
public override IEnumerable<object[]> GetData(MethodInfo testMethod)
{
var methodParameters = testMethod.GetParameters();
if (methodParameters.Length < _environmentVariableNames.Length)
public EnvironmentDataAttribute(params string[] environmentVariableNames)
{
throw new ArgumentException($"The target test method only has {methodParameters.Length} arguments but you supplied {_environmentVariableNames.Length}");
_environmentVariableNames = environmentVariableNames;
}
var values = new object[_environmentVariableNames.Length];
for (var i = 0; i < _environmentVariableNames.Length; i++)
public override IEnumerable<object[]> GetData(MethodInfo testMethod)
{
values[i] = Convert.ChangeType(Environment.GetEnvironmentVariable(_environmentVariableNames[i]), methodParameters[i].ParameterType);
}
var methodParameters = testMethod.GetParameters();
return new[] { values };
if (methodParameters.Length < _environmentVariableNames.Length)
{
throw new ArgumentException($"The target test method only has {methodParameters.Length} arguments but you supplied {_environmentVariableNames.Length}");
}
var values = new object[_environmentVariableNames.Length];
for (var i = 0; i < _environmentVariableNames.Length; i++)
{
values[i] = Convert.ChangeType(Environment.GetEnvironmentVariable(_environmentVariableNames[i]), methodParameters[i].ParameterType);
}
return new[] { values };
}
}
}

View File

@ -3,19 +3,20 @@ using AutoFixture.Xunit2;
using Xunit;
using Xunit.Sdk;
namespace Bit.Test.Common.AutoFixture.Attributes;
public class InlineCustomAutoDataAttribute : CompositeDataAttribute
namespace Bit.Test.Common.AutoFixture.Attributes
{
public InlineCustomAutoDataAttribute(Type[] iCustomizationTypes, params object[] values) : base(new DataAttribute[] {
new InlineDataAttribute(values),
new CustomAutoDataAttribute(iCustomizationTypes)
})
{ }
public class InlineCustomAutoDataAttribute : CompositeDataAttribute
{
public InlineCustomAutoDataAttribute(Type[] iCustomizationTypes, params object[] values) : base(new DataAttribute[] {
new InlineDataAttribute(values),
new CustomAutoDataAttribute(iCustomizationTypes)
})
{ }
public InlineCustomAutoDataAttribute(ICustomization[] customizations, params object[] values) : base(new DataAttribute[] {
new InlineDataAttribute(values),
new CustomAutoDataAttribute(customizations)
})
{ }
public InlineCustomAutoDataAttribute(ICustomization[] customizations, params object[] values) : base(new DataAttribute[] {
new InlineDataAttribute(values),
new CustomAutoDataAttribute(customizations)
})
{ }
}
}

View File

@ -1,17 +1,18 @@
using AutoFixture;
namespace Bit.Test.Common.AutoFixture.Attributes;
public class InlineSutAutoDataAttribute : InlineCustomAutoDataAttribute
namespace Bit.Test.Common.AutoFixture.Attributes
{
public InlineSutAutoDataAttribute(params object[] values) : base(
new Type[] { typeof(SutProviderCustomization) }, values)
{ }
public InlineSutAutoDataAttribute(Type[] iCustomizationTypes, params object[] values) : base(
iCustomizationTypes.Append(typeof(SutProviderCustomization)).ToArray(), values)
{ }
public class InlineSutAutoDataAttribute : InlineCustomAutoDataAttribute
{
public InlineSutAutoDataAttribute(params object[] values) : base(
new Type[] { typeof(SutProviderCustomization) }, values)
{ }
public InlineSutAutoDataAttribute(Type[] iCustomizationTypes, params object[] values) : base(
iCustomizationTypes.Append(typeof(SutProviderCustomization)).ToArray(), values)
{ }
public InlineSutAutoDataAttribute(ICustomization[] customizations, params object[] values) : base(
customizations.Append(new SutProviderCustomization()).ToArray(), values)
{ }
public InlineSutAutoDataAttribute(ICustomization[] customizations, params object[] values) : base(
customizations.Append(new SutProviderCustomization()).ToArray(), values)
{ }
}
}

View File

@ -1,10 +1,11 @@
using AutoFixture;
using Bit.Test.Common.AutoFixture.JsonDocumentFixtures;
namespace Bit.Test.Common.AutoFixture.Attributes;
public class JsonDocumentCustomizeAttribute : BitCustomizeAttribute
namespace Bit.Test.Common.AutoFixture.Attributes
{
public string Json { get; set; }
public override ICustomization GetCustomization() => new JsonDocumentCustomization() { Json = Json };
public class JsonDocumentCustomizeAttribute : BitCustomizeAttribute
{
public string Json { get; set; }
public override ICustomization GetCustomization() => new JsonDocumentCustomization() { Json = Json };
}
}

View File

@ -1,37 +1,38 @@
using Xunit;
namespace Bit.Test.Common.AutoFixture.Attributes;
/// <summary>
/// Used for requiring certain environment variables exist at the time. Mostly used for more edge unit tests that shouldn't
/// be run during CI builds or should only be ran in CI builds when pieces of information are available.
/// </summary>
public class RequiredEnvironmentTheoryAttribute : TheoryAttribute
namespace Bit.Test.Common.AutoFixture.Attributes
{
private readonly string[] _environmentVariableNames;
public RequiredEnvironmentTheoryAttribute(params string[] environmentVariableNames)
/// <summary>
/// Used for requiring certain environment variables exist at the time. Mostly used for more edge unit tests that shouldn't
/// be run during CI builds or should only be ran in CI builds when pieces of information are available.
/// </summary>
public class RequiredEnvironmentTheoryAttribute : TheoryAttribute
{
_environmentVariableNames = environmentVariableNames;
private readonly string[] _environmentVariableNames;
if (!HasRequiredEnvironmentVariables())
public RequiredEnvironmentTheoryAttribute(params string[] environmentVariableNames)
{
Skip = $"Missing one or more required environment variables. ({string.Join(", ", _environmentVariableNames)})";
}
}
_environmentVariableNames = environmentVariableNames;
private bool HasRequiredEnvironmentVariables()
{
foreach (var env in _environmentVariableNames)
{
var value = Environment.GetEnvironmentVariable(env);
if (value == null)
if (!HasRequiredEnvironmentVariables())
{
return false;
Skip = $"Missing one or more required environment variables. ({string.Join(", ", _environmentVariableNames)})";
}
}
return true;
private bool HasRequiredEnvironmentVariables()
{
foreach (var env in _environmentVariableNames)
{
var value = Environment.GetEnvironmentVariable(env);
if (value == null)
{
return false;
}
}
return true;
}
}
}

View File

@ -1,15 +1,16 @@
using AutoFixture;
namespace Bit.Test.Common.AutoFixture.Attributes;
public class SutProviderCustomizeAttribute : BitCustomizeAttribute
namespace Bit.Test.Common.AutoFixture.Attributes
{
public override ICustomization GetCustomization() => new SutProviderCustomization();
}
public class SutProviderCustomizeAttribute : BitCustomizeAttribute
{
public override ICustomization GetCustomization() => new SutProviderCustomization();
}
public class SutAutoDataAttribute : CustomAutoDataAttribute
{
public SutAutoDataAttribute(params Type[] iCustomizationTypes) : base(
iCustomizationTypes.Append(typeof(SutProviderCustomization)).ToArray())
{ }
public class SutAutoDataAttribute : CustomAutoDataAttribute
{
public SutAutoDataAttribute(params Type[] iCustomizationTypes) : base(
iCustomizationTypes.Append(typeof(SutProviderCustomization)).ToArray())
{ }
}
}

View File

@ -1,38 +1,39 @@
using AutoFixture;
using AutoFixture.Kernel;
namespace Bit.Test.Common.AutoFixture;
public class BuilderWithoutAutoProperties : ISpecimenBuilder
namespace Bit.Test.Common.AutoFixture
{
private readonly Type _type;
public BuilderWithoutAutoProperties(Type type)
public class BuilderWithoutAutoProperties : ISpecimenBuilder
{
_type = type;
}
public object Create(object request, ISpecimenContext context)
{
if (context == null)
private readonly Type _type;
public BuilderWithoutAutoProperties(Type type)
{
throw new ArgumentNullException(nameof(context));
_type = type;
}
var type = request as Type;
if (type == null || type != _type)
public object Create(object request, ISpecimenContext context)
{
return new NoSpecimen();
}
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
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);
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<T> : ISpecimenBuilder
{
public object Create(object request, ISpecimenContext context) =>
new BuilderWithoutAutoProperties(typeof(T)).Create(request, context);
}
}
public class BuilderWithoutAutoProperties<T> : ISpecimenBuilder
{
public object Create(object request, ISpecimenContext context) =>
new BuilderWithoutAutoProperties(typeof(T)).Create(request, context);
}

View File

@ -2,31 +2,32 @@
using Microsoft.AspNetCore.Mvc;
using Org.BouncyCastle.Security;
namespace Bit.Test.Common.AutoFixture;
/// <summary>
/// Disables setting of Auto Properties on the Controller to avoid ASP.net initialization errors. Still sets constructor dependencies.
/// </summary>
/// <param name="fixture"></param>
public class ControllerCustomization : ICustomization
namespace Bit.Test.Common.AutoFixture
{
private readonly Type _controllerType;
public ControllerCustomization(Type controllerType)
/// <summary>
/// Disables setting of Auto Properties on the Controller to avoid ASP.net initialization errors. Still sets constructor dependencies.
/// </summary>
/// <param name="fixture"></param>
public class ControllerCustomization : ICustomization
{
if (!controllerType.IsAssignableTo(typeof(Controller)))
private readonly Type _controllerType;
public ControllerCustomization(Type controllerType)
{
throw new InvalidParameterException($"{nameof(controllerType)} must derive from {typeof(Controller).Name}");
if (!controllerType.IsAssignableTo(typeof(Controller)))
{
throw new InvalidParameterException($"{nameof(controllerType)} must derive from {typeof(Controller).Name}");
}
_controllerType = controllerType;
}
_controllerType = controllerType;
public void Customize(IFixture fixture)
{
fixture.Customizations.Add(new BuilderWithoutAutoProperties(_controllerType));
}
}
public void Customize(IFixture fixture)
public class ControllerCustomization<T> : ICustomization where T : Controller
{
fixture.Customizations.Add(new BuilderWithoutAutoProperties(_controllerType));
public void Customize(IFixture fixture) => new ControllerCustomization(typeof(T)).Customize(fixture);
}
}
public class ControllerCustomization<T> : ICustomization where T : Controller
{
public void Customize(IFixture fixture) => new ControllerCustomization(typeof(T)).Customize(fixture);
}

View File

@ -1,13 +1,14 @@
using AutoFixture;
using AutoFixture.AutoNSubstitute;
namespace Bit.Test.Common.AutoFixture;
public static class FixtureExtensions
namespace Bit.Test.Common.AutoFixture
{
public static IFixture WithAutoNSubstitutions(this IFixture fixture)
=> fixture.Customize(new AutoNSubstituteCustomization());
public static class FixtureExtensions
{
public static IFixture WithAutoNSubstitutions(this IFixture fixture)
=> fixture.Customize(new AutoNSubstituteCustomization());
public static IFixture WithAutoNSubstitutionsAutoPopulatedProperties(this IFixture fixture)
=> fixture.Customize(new AutoNSubstituteCustomization { ConfigureMembers = true });
public static IFixture WithAutoNSubstitutionsAutoPopulatedProperties(this IFixture fixture)
=> fixture.Customize(new AutoNSubstituteCustomization { ConfigureMembers = true });
}
}

View File

@ -1,15 +1,16 @@
using AutoFixture;
namespace Bit.Test.Common.AutoFixture;
public class GlobalSettings : ICustomization
namespace Bit.Test.Common.AutoFixture
{
public void Customize(IFixture fixture)
public class GlobalSettings : ICustomization
{
fixture.Customize<Bit.Core.Settings.GlobalSettings>(composer => composer
.Without(s => s.BaseServiceUri)
.Without(s => s.Attachment)
.Without(s => s.Send)
.Without(s => s.DataProtection));
public void Customize(IFixture fixture)
{
fixture.Customize<Bit.Core.Settings.GlobalSettings>(composer => composer
.Without(s => s.BaseServiceUri)
.Without(s => s.Attachment)
.Without(s => s.Send)
.Without(s => s.DataProtection));
}
}
}

View File

@ -1,7 +1,8 @@
namespace Bit.Test.Common.AutoFixture;
public interface ISutProvider
namespace Bit.Test.Common.AutoFixture
{
Type SutType { get; }
ISutProvider Create();
public interface ISutProvider
{
Type SutType { get; }
ISutProvider Create();
}
}

View File

@ -2,30 +2,31 @@
using AutoFixture;
using AutoFixture.Kernel;
namespace Bit.Test.Common.AutoFixture.JsonDocumentFixtures;
public class JsonDocumentCustomization : ICustomization, ISpecimenBuilder
namespace Bit.Test.Common.AutoFixture.JsonDocumentFixtures
{
public string Json { get; set; }
public void Customize(IFixture fixture)
public class JsonDocumentCustomization : ICustomization, ISpecimenBuilder
{
fixture.Customizations.Add(this);
}
public object Create(object request, ISpecimenContext context)
{
if (context == null)
public string Json { get; set; }
public void Customize(IFixture fixture)
{
throw new ArgumentNullException(nameof(context));
}
var type = request as Type;
if (type == null || (type != typeof(JsonDocument)))
{
return new NoSpecimen();
fixture.Customizations.Add(this);
}
return JsonDocument.Parse(Json ?? "{}");
public object Create(object request, ISpecimenContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
var type = request as Type;
if (type == null || (type != typeof(JsonDocument)))
{
return new NoSpecimen();
}
return JsonDocument.Parse(Json ?? "{}");
}
}
}

View File

@ -2,132 +2,133 @@
using AutoFixture;
using AutoFixture.Kernel;
namespace Bit.Test.Common.AutoFixture;
public class SutProvider<TSut> : ISutProvider
namespace Bit.Test.Common.AutoFixture
{
private Dictionary<Type, Dictionary<string, object>> _dependencies;
private readonly IFixture _fixture;
private readonly ConstructorParameterRelay<TSut> _constructorParameterRelay;
public TSut Sut { get; private set; }
public Type SutType => typeof(TSut);
public SutProvider() : this(new Fixture()) { }
public SutProvider(IFixture fixture)
public class SutProvider<TSut> : ISutProvider
{
_dependencies = new Dictionary<Type, Dictionary<string, object>>();
_fixture = (fixture ?? new Fixture()).WithAutoNSubstitutions().Customize(new GlobalSettings());
_constructorParameterRelay = new ConstructorParameterRelay<TSut>(this, _fixture);
_fixture.Customizations.Add(_constructorParameterRelay);
}
private Dictionary<Type, Dictionary<string, object>> _dependencies;
private readonly IFixture _fixture;
private readonly ConstructorParameterRelay<TSut> _constructorParameterRelay;
public SutProvider<TSut> SetDependency<T>(T dependency, string parameterName = "")
=> SetDependency(typeof(T), dependency, parameterName);
public SutProvider<TSut> SetDependency(Type dependencyType, object dependency, string parameterName = "")
{
if (_dependencies.ContainsKey(dependencyType))
public TSut Sut { get; private set; }
public Type SutType => typeof(TSut);
public SutProvider() : this(new Fixture()) { }
public SutProvider(IFixture fixture)
{
_dependencies[dependencyType][parameterName] = dependency;
}
else
{
_dependencies[dependencyType] = new Dictionary<string, object> { { parameterName, dependency } };
_dependencies = new Dictionary<Type, Dictionary<string, object>>();
_fixture = (fixture ?? new Fixture()).WithAutoNSubstitutions().Customize(new GlobalSettings());
_constructorParameterRelay = new ConstructorParameterRelay<TSut>(this, _fixture);
_fixture.Customizations.Add(_constructorParameterRelay);
}
return this;
}
public T GetDependency<T>(string parameterName = "") => (T)GetDependency(typeof(T), parameterName);
public object GetDependency(Type dependencyType, string parameterName = "")
{
if (DependencyIsSet(dependencyType, parameterName))
public SutProvider<TSut> SetDependency<T>(T dependency, string parameterName = "")
=> SetDependency(typeof(T), dependency, parameterName);
public SutProvider<TSut> SetDependency(Type dependencyType, object dependency, string parameterName = "")
{
return _dependencies[dependencyType][parameterName];
}
else if (_dependencies.ContainsKey(dependencyType))
{
var knownDependencies = _dependencies[dependencyType];
if (knownDependencies.Values.Count == 1)
if (_dependencies.ContainsKey(dependencyType))
{
return _dependencies[dependencyType].Values.Single();
_dependencies[dependencyType][parameterName] = dependency;
}
else
{
throw new ArgumentException(string.Concat($"Dependency of type {dependencyType.Name} and name ",
$"{parameterName} does not exist. Available dependency names are: ",
string.Join(", ", knownDependencies.Keys)));
_dependencies[dependencyType] = new Dictionary<string, object> { { parameterName, dependency } };
}
}
else
{
throw new ArgumentException($"Dependency of type {dependencyType.Name} and name {parameterName} has not been set.");
}
}
public void Reset()
{
_dependencies = new Dictionary<Type, Dictionary<string, object>>();
Sut = default;
}
ISutProvider ISutProvider.Create() => Create();
public SutProvider<TSut> Create()
{
Sut = _fixture.Create<TSut>();
return this;
}
private bool DependencyIsSet(Type dependencyType, string parameterName = "")
=> _dependencies.ContainsKey(dependencyType) && _dependencies[dependencyType].ContainsKey(parameterName);
private object GetDefault(Type type) => type.IsValueType ? Activator.CreateInstance(type) : null;
private class ConstructorParameterRelay<T> : ISpecimenBuilder
{
private readonly SutProvider<T> _sutProvider;
private readonly IFixture _fixture;
public ConstructorParameterRelay(SutProvider<T> sutProvider, IFixture fixture)
{
_sutProvider = sutProvider;
_fixture = fixture;
return this;
}
public object Create(object request, ISpecimenContext context)
public T GetDependency<T>(string parameterName = "") => (T)GetDependency(typeof(T), parameterName);
public object GetDependency(Type dependencyType, string parameterName = "")
{
if (context == null)
if (DependencyIsSet(dependencyType, parameterName))
{
throw new ArgumentNullException(nameof(context));
return _dependencies[dependencyType][parameterName];
}
if (!(request is ParameterInfo parameterInfo))
else if (_dependencies.ContainsKey(dependencyType))
{
return new NoSpecimen();
var knownDependencies = _dependencies[dependencyType];
if (knownDependencies.Values.Count == 1)
{
return _dependencies[dependencyType].Values.Single();
}
else
{
throw new ArgumentException(string.Concat($"Dependency of type {dependencyType.Name} and name ",
$"{parameterName} does not exist. Available dependency names are: ",
string.Join(", ", knownDependencies.Keys)));
}
}
if (parameterInfo.Member.DeclaringType != typeof(T) ||
parameterInfo.Member.MemberType != MemberTypes.Constructor)
else
{
return new NoSpecimen();
throw new ArgumentException($"Dependency of type {dependencyType.Name} and name {parameterName} has not been set.");
}
}
public void Reset()
{
_dependencies = new Dictionary<Type, Dictionary<string, object>>();
Sut = default;
}
ISutProvider ISutProvider.Create() => Create();
public SutProvider<TSut> Create()
{
Sut = _fixture.Create<TSut>();
return this;
}
private bool DependencyIsSet(Type dependencyType, string parameterName = "")
=> _dependencies.ContainsKey(dependencyType) && _dependencies[dependencyType].ContainsKey(parameterName);
private object GetDefault(Type type) => type.IsValueType ? Activator.CreateInstance(type) : null;
private class ConstructorParameterRelay<T> : ISpecimenBuilder
{
private readonly SutProvider<T> _sutProvider;
private readonly IFixture _fixture;
public ConstructorParameterRelay(SutProvider<T> sutProvider, IFixture fixture)
{
_sutProvider = sutProvider;
_fixture = fixture;
}
if (_sutProvider.DependencyIsSet(parameterInfo.ParameterType, parameterInfo.Name))
public object Create(object request, ISpecimenContext context)
{
return _sutProvider.GetDependency(parameterInfo.ParameterType, parameterInfo.Name);
}
// Return default type if set
else if (_sutProvider.DependencyIsSet(parameterInfo.ParameterType, ""))
{
return _sutProvider.GetDependency(parameterInfo.ParameterType, "");
}
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
if (!(request is ParameterInfo parameterInfo))
{
return new NoSpecimen();
}
if (parameterInfo.Member.DeclaringType != typeof(T) ||
parameterInfo.Member.MemberType != MemberTypes.Constructor)
{
return new NoSpecimen();
}
if (_sutProvider.DependencyIsSet(parameterInfo.ParameterType, parameterInfo.Name))
{
return _sutProvider.GetDependency(parameterInfo.ParameterType, parameterInfo.Name);
}
// Return default type if set
else if (_sutProvider.DependencyIsSet(parameterInfo.ParameterType, ""))
{
return _sutProvider.GetDependency(parameterInfo.ParameterType, "");
}
// This is the equivalent of _fixture.Create<parameterInfo.ParameterType>, but no overload for
// Create(Type type) exists.
var dependency = new SpecimenContext(_fixture).Resolve(new SeededRequest(parameterInfo.ParameterType,
_sutProvider.GetDefault(parameterInfo.ParameterType)));
_sutProvider.SetDependency(parameterInfo.ParameterType, dependency, parameterInfo.Name);
return dependency;
// This is the equivalent of _fixture.Create<parameterInfo.ParameterType>, but no overload for
// Create(Type type) exists.
var dependency = new SpecimenContext(_fixture).Resolve(new SeededRequest(parameterInfo.ParameterType,
_sutProvider.GetDefault(parameterInfo.ParameterType)));
_sutProvider.SetDependency(parameterInfo.ParameterType, dependency, parameterInfo.Name);
return dependency;
}
}
}
}

View File

@ -1,33 +1,34 @@
using AutoFixture;
using AutoFixture.Kernel;
namespace Bit.Test.Common.AutoFixture.Attributes;
public class SutProviderCustomization : ICustomization, ISpecimenBuilder
namespace Bit.Test.Common.AutoFixture.Attributes
{
private IFixture _fixture = null;
public object Create(object request, ISpecimenContext context)
public class SutProviderCustomization : ICustomization, ISpecimenBuilder
{
if (context == null)
private IFixture _fixture = null;
public object Create(object request, ISpecimenContext context)
{
throw new ArgumentNullException(nameof(context));
}
if (!(request is Type typeRequest))
{
return new NoSpecimen();
}
if (!typeof(ISutProvider).IsAssignableFrom(typeRequest))
{
return new NoSpecimen();
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
if (!(request is Type typeRequest))
{
return new NoSpecimen();
}
if (!typeof(ISutProvider).IsAssignableFrom(typeRequest))
{
return new NoSpecimen();
}
return ((ISutProvider)Activator.CreateInstance(typeRequest, _fixture)).Create();
}
return ((ISutProvider)Activator.CreateInstance(typeRequest, _fixture)).Create();
}
public void Customize(IFixture fixture)
{
_fixture = fixture;
fixture.Customizations.Add(this);
public void Customize(IFixture fixture)
{
_fixture = fixture;
fixture.Customizations.Add(this);
}
}
}