├── GitVersion.yml ├── images └── icon.png ├── src ├── public.snk ├── qodana.yaml ├── Objectivity.AutoFixture.XUnit2.Core │ ├── Factories │ │ ├── IFactory.cs │ │ └── NegativeValuesRequestFactory.cs │ ├── MemberData │ │ ├── IDataItemExtender.cs │ │ └── MemberAutoDataItemExtender.cs │ ├── Providers │ │ ├── IAutoFixtureAttributeProvider.cs │ │ ├── IAutoFixtureInlineAttributeProvider.cs │ │ ├── AutoDataAttributeProvider.cs │ │ └── InlineAutoDataAttributeProvider.cs │ ├── Requests │ │ ├── FixedValuesRequest.cs │ │ ├── ExceptValuesRequest.cs │ │ └── ValuesRequest.cs │ ├── Common │ │ ├── ValidatedNotNullAttribute.cs │ │ ├── Check.cs │ │ ├── RoundRobinEnumerable[T].cs │ │ └── EnumerableExtensions.cs │ ├── Customizations │ │ ├── OmitOnRecursionCustomization.cs │ │ ├── DoNotThrowOnRecursionCustomization.cs │ │ ├── IgnoreVirtualMembersCustomization.cs │ │ └── AutoDataCommonCustomization.cs │ ├── Attributes │ │ ├── CustomizeWithAttribute[T].cs │ │ ├── IgnoreVirtualMembersAttribute.cs │ │ ├── PickNegativeAttribute.cs │ │ ├── AutoDataBaseAttribute.cs │ │ ├── ExceptAttribute.cs │ │ ├── PickFromValuesAttribute.cs │ │ ├── CustomizeWithAttribute.cs │ │ ├── InlineAutoDataBaseAttribute.cs │ │ ├── PickFromRangeAttribute.cs │ │ ├── AutoDataAdapterAttribute.cs │ │ └── MemberAutoDataBaseAttribute.cs │ ├── Comparers │ │ └── CustomizeAttributeComparer.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── SpecimenBuilders │ │ ├── IgnoreVirtualMembersSpecimenBuilder.cs │ │ ├── RandomExceptValuesGenerator.cs │ │ ├── RandomFixedValuesGenerator.cs │ │ └── RequestFactoryRelay.cs │ └── Objectivity.AutoFixture.XUnit2.Core.csproj ├── Objectivity.AutoFixture.XUnit2.AutoMoq.Tests │ ├── IFakeObjectUnderTest.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── .editorconfig │ └── Attributes │ │ ├── AutoMockDataAttributeTests.cs │ │ └── InlineAutoMockDataAttributeTests.cs ├── Objectivity.AutoFixture.XUnit2.AutoFakeItEasy.Tests │ ├── IFakeObjectUnderTest.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── .editorconfig │ └── Attributes │ │ └── AutoMockDataAttributeTests.cs ├── Objectivity.AutoFixture.XUnit2.AutoNSubstitute.Tests │ ├── IFakeObjectUnderTest.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── .editorconfig │ └── Attributes │ │ ├── AutoMockDataAttributeTests.cs │ │ └── InlineAutoMockDataAttributeTests.cs ├── Objectivity.AutoFixture.XUnit2.Core.Tests │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── Customizations │ │ ├── OmitOnRecursionCustomizationTests.cs │ │ ├── DoNotThrowOnRecursionCustomizationTests.cs │ │ ├── AutoDataCommonCustomizationTests.cs │ │ └── IgnoreVirtualMembersCustomizationTests.cs │ ├── Providers │ │ ├── AutoDataAttributeProviderTests.cs │ │ └── InlineAutoDataAttributeProviderTests.cs │ ├── Common │ │ ├── CheckTests.cs │ │ ├── RoundRobinEnumerableTests.cs │ │ └── EnumerableExtensionsTests.cs │ ├── Comparers │ │ └── CustomizeAttributeComparerTests.cs │ ├── .editorconfig │ ├── FixtureAssertionExtensions.cs │ ├── Attributes │ │ ├── AutoDataBaseAttributeTests.cs │ │ ├── MemberAutoDataBaseAttributeTests.cs │ │ └── InlineAutoDataBaseAttributeTests.cs │ ├── SpecimenBuilders │ │ ├── RandomExceptValuesGeneratorTests.cs │ │ └── RandomFixedValuesGeneratorTests.cs │ └── MemberData │ │ └── MemberAutoDataItemExtenderTests.cs ├── Directory.Build.props ├── CodeAnalysisDictionary.xml ├── Objectivity.AutoFixture.XUnit2.AutoMoq │ ├── Properties │ │ └── AssemblyInfo.cs │ └── Attributes │ │ ├── AutoMockDataAttribute.cs │ │ ├── InlineAutoMockDataAttribute.cs │ │ └── MemberAutoMockDataAttribute.cs ├── Objectivity.AutoFixture.XUnit2.AutoFakeItEasy │ ├── Properties │ │ └── AssemblyInfo.cs │ └── Attributes │ │ ├── AutoMockDataAttribute.cs │ │ ├── InlineAutoMockDataAttribute.cs │ │ └── MemberAutoMockDataAttribute.cs ├── Objectivity.AutoFixture.XUnit2.AutoNSubstitute │ ├── Properties │ │ └── AssemblyInfo.cs │ └── Attributes │ │ ├── AutoMockDataAttribute.cs │ │ ├── InlineAutoMockDataAttribute.cs │ │ └── MemberAutoMockDataAttribute.cs ├── Objectivity.AutoFixture.XUnit2.Core.sln ├── Objectivity.AutoFixture.XUnit2.AutoMoq.sln ├── Objectivity.AutoFixture.XUnit2.AutoFakeItEasy.sln ├── Objectivity.AutoFixture.XUnit2.AutoNSubstitute.sln └── Objectivity.AutoFixture.XUnit2.AutoMock.sln ├── stryker-config.yml ├── .github ├── actions │ ├── determine-next-version │ │ └── action.yml │ ├── materialize-signing-key │ │ └── action.yml │ └── test-and-collect-coverage │ │ └── action.yml ├── dependabot.yml └── workflows │ ├── fossa-scan.yml │ ├── tag.yml │ ├── publish.yml │ ├── semgrep.yml │ ├── codeql.yml │ ├── test-mutations.yml │ ├── snyk.yml │ ├── qodana.yml │ ├── init.yml │ ├── cicd.yml │ └── build-test-pack.yml └── LICENSE /GitVersion.yml: -------------------------------------------------------------------------------- 1 | mode: ContinuousDelivery -------------------------------------------------------------------------------- /images/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Accenture/AutoFixture.XUnit2.AutoMock/HEAD/images/icon.png -------------------------------------------------------------------------------- /src/public.snk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Accenture/AutoFixture.XUnit2.AutoMock/HEAD/src/public.snk -------------------------------------------------------------------------------- /stryker-config.yml: -------------------------------------------------------------------------------- 1 | stryker-config: 2 | solution: 'Objectivity.AutoFixture.XUnit2.AutoMock.sln' 3 | project-info: 4 | name: 'github.com/Accenture/AutoFixture.XUnit2.AutoMock' -------------------------------------------------------------------------------- /src/qodana.yaml: -------------------------------------------------------------------------------- 1 | version: "1.0" 2 | profile: 3 | name: qodana.recommended 4 | linter: jetbrains/qodana-cdnet:2025.2-eap 5 | dotnet: 6 | solution: Objectivity.AutoFixture.XUnit2.AutoMock.sln 7 | configuration: Release 8 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.Core/Factories/IFactory.cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.Core.Factories 2 | { 3 | internal interface IFactory 4 | { 5 | TOutput Create(TInput input); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.Core/MemberData/IDataItemExtender.cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.Core.MemberData 2 | { 3 | using System.Reflection; 4 | 5 | public interface IDataItemExtender 6 | { 7 | object[] Extend(MethodInfo testMethod, object[] values); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.Core/Providers/IAutoFixtureAttributeProvider.cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.Core.Providers 2 | { 3 | using global::AutoFixture; 4 | 5 | using Xunit.Sdk; 6 | 7 | public interface IAutoFixtureAttributeProvider 8 | { 9 | DataAttribute GetAttribute(IFixture fixture); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.Core/Providers/IAutoFixtureInlineAttributeProvider.cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.Core.Providers 2 | { 3 | using global::AutoFixture; 4 | 5 | using Xunit.Sdk; 6 | 7 | public interface IAutoFixtureInlineAttributeProvider 8 | { 9 | DataAttribute GetAttribute(IFixture fixture, params object[] values); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.AutoMoq.Tests/IFakeObjectUnderTest.cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.AutoMoq.Tests 2 | { 3 | using System.Diagnostics.CodeAnalysis; 4 | 5 | public interface IFakeObjectUnderTest 6 | { 7 | [SuppressMessage("ReSharper", "UnusedMember.Global", Justification = "Required for test.")] 8 | string StringProperty { get; set; } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.AutoFakeItEasy.Tests/IFakeObjectUnderTest.cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.AutoFakeItEasy.Tests 2 | { 3 | using System.Diagnostics.CodeAnalysis; 4 | 5 | public interface IFakeObjectUnderTest 6 | { 7 | [SuppressMessage("ReSharper", "UnusedMember.Global", Justification = "Required for test.")] 8 | string StringProperty { get; set; } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.Core/Requests/FixedValuesRequest.cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.Core.Requests 2 | { 3 | using System; 4 | 5 | internal sealed class FixedValuesRequest : ValuesRequest 6 | { 7 | public FixedValuesRequest(Type operandType, params object[] values) 8 | : base(operandType, values) 9 | { 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.AutoNSubstitute.Tests/IFakeObjectUnderTest.cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.AutoNSubstitute.Tests 2 | { 3 | using System.Diagnostics.CodeAnalysis; 4 | 5 | public interface IFakeObjectUnderTest 6 | { 7 | [SuppressMessage("ReSharper", "UnusedMember.Global", Justification = "Required for test.")] 8 | string StringProperty { get; set; } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.Core/Requests/ExceptValuesRequest.cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.Core.Requests 2 | { 3 | using System; 4 | 5 | internal sealed class ExceptValuesRequest : ValuesRequest 6 | { 7 | public ExceptValuesRequest(Type operandType, params object[] values) 8 | : base(operandType, values) 9 | { 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.AutoMoq.Tests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | 3 | // Setting ComVisible to false makes the types in this assembly not visible 4 | // to COM components. If you need to access a type in this assembly from 5 | // COM, set the ComVisible attribute to true on that type. 6 | [assembly: ComVisible(false)] 7 | 8 | // The following GUID is for the ID of the typelib if this project is exposed to COM 9 | [assembly: Guid("6E0FA92A-AC76-453E-A58F-CEB06492D2FB")] 10 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.Core.Tests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | 3 | // Setting ComVisible to false makes the types in this assembly not visible 4 | // to COM components. If you need to access a type in this assembly from 5 | // COM, set the ComVisible attribute to true on that type. 6 | [assembly: ComVisible(false)] 7 | 8 | // The following GUID is for the ID of the typelib if this project is exposed to COM 9 | [assembly: Guid("be5bf6e2-2edc-4223-a89b-ae1d4be1ff4e")] 10 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.AutoFakeItEasy.Tests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | 3 | // Setting ComVisible to false makes the types in this assembly not visible 4 | // to COM components. If you need to access a type in this assembly from 5 | // COM, set the ComVisible attribute to true on that type. 6 | [assembly: ComVisible(false)] 7 | 8 | // The following GUID is for the ID of the typelib if this project is exposed to COM 9 | [assembly: Guid("1ACF081C-FE22-41BD-BB22-033D2572D424")] 10 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.AutoNSubstitute.Tests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | 3 | // Setting ComVisible to false makes the types in this assembly not visible 4 | // to COM components. If you need to access a type in this assembly from 5 | // COM, set the ComVisible attribute to true on that type. 6 | [assembly: ComVisible(false)] 7 | 8 | // The following GUID is for the ID of the typelib if this project is exposed to COM 9 | [assembly: Guid("05464055-95ca-4bd8-a1c4-9e01885351b3")] 10 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.Core/Common/ValidatedNotNullAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.Core.Common 2 | { 3 | using System; 4 | using System.Diagnostics.CodeAnalysis; 5 | 6 | [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false)] 7 | [SuppressMessage("ReSharper", "RedundantTypeDeclarationBody", Justification = "Indicates to Code Analysis that a method validates a particular parameter.")] 8 | internal sealed class ValidatedNotNullAttribute : Attribute 9 | { 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.Core/Providers/AutoDataAttributeProvider.cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.Core.Providers 2 | { 3 | using global::AutoFixture; 4 | 5 | using Objectivity.AutoFixture.XUnit2.Core.Attributes; 6 | 7 | using Xunit.Sdk; 8 | 9 | public sealed class AutoDataAttributeProvider : IAutoFixtureAttributeProvider 10 | { 11 | public DataAttribute GetAttribute(IFixture fixture) 12 | { 13 | return new AutoDataAdapterAttribute(fixture); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | true 4 | 1.0.0.0 5 | Accenture 6 | $(Company) 7 | Copyright (c) $(Company) 8 | $(AssemblyName) 9 | $(AssemblyName) 10 | 11 | -------------------------------------------------------------------------------- /.github/actions/determine-next-version/action.yml: -------------------------------------------------------------------------------- 1 | name: Determine next version 2 | description: Determines next version for building and packing 3 | outputs: 4 | version: 5 | description: Next version 6 | value: ${{ steps.gitversion.outputs.MajorMinorPatch }} 7 | runs: 8 | using: composite 9 | steps: 10 | - name: 🗜️ install GitVersion 11 | uses: gittools/actions/gitversion/setup@v0 12 | with: 13 | versionSpec: '5.x' 14 | - name: 🎱 determine version 15 | id: gitversion 16 | uses: gittools/actions/gitversion/execute@v0 17 | with: 18 | useConfigFile: true 19 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.Core/Providers/InlineAutoDataAttributeProvider.cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.Core.Providers 2 | { 3 | using global::AutoFixture; 4 | 5 | using Objectivity.AutoFixture.XUnit2.Core.Attributes; 6 | 7 | using Xunit.Sdk; 8 | 9 | public sealed class InlineAutoDataAttributeProvider : IAutoFixtureInlineAttributeProvider 10 | { 11 | public DataAttribute GetAttribute(IFixture fixture, params object[] values) 12 | { 13 | return new AutoDataAdapterAttribute(fixture, values); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.Core/Customizations/OmitOnRecursionCustomization.cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.Core.Customizations 2 | { 3 | using global::AutoFixture; 4 | 5 | using Objectivity.AutoFixture.XUnit2.Core.Common; 6 | 7 | public class OmitOnRecursionCustomization : ICustomization 8 | { 9 | public void Customize(IFixture fixture) 10 | { 11 | // Omit recursion on first level. 12 | fixture.NotNull(nameof(fixture)) 13 | .Behaviors 14 | .Add(new OmitOnRecursionBehavior()); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/CodeAnalysisDictionary.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Moq 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.Core/Customizations/DoNotThrowOnRecursionCustomization.cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.Core.Customizations 2 | { 3 | using System.Linq; 4 | 5 | using global::AutoFixture; 6 | 7 | using Objectivity.AutoFixture.XUnit2.Core.Common; 8 | 9 | public class DoNotThrowOnRecursionCustomization : ICustomization 10 | { 11 | public void Customize(IFixture fixture) 12 | { 13 | // Do not throw exception on circular references. 14 | fixture.NotNull(nameof(fixture)) 15 | .Behaviors 16 | .OfType() 17 | .ToList() 18 | .ForEach(b => fixture.Behaviors.Remove(b)); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "nuget" 4 | directories: 5 | - "**/*" 6 | schedule: 7 | interval: "weekly" 8 | day: "sunday" 9 | time: "03:00" 10 | timezone: "Europe/Warsaw" 11 | groups: 12 | xUnit: 13 | patterns: 14 | - "xunit" 15 | - "xunit.*" 16 | - "xunit.runner.*" 17 | AutoFixture: 18 | patterns: 19 | - "AutoFixture*" 20 | Analyzers: 21 | patterns: 22 | - "*analyzer*" 23 | exclude-patterns: 24 | - "xunit.analyzers" 25 | ignore: 26 | - dependency-name: "Moq" 27 | - package-ecosystem: "github-actions" 28 | directory: "/" 29 | schedule: 30 | interval: "weekly" 31 | day: "sunday" 32 | time: "02:00" 33 | timezone: "Europe/Warsaw" 34 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.Core/Attributes/CustomizeWithAttribute[T].cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.Core.Attributes 2 | { 3 | using System; 4 | using System.Diagnostics.CodeAnalysis; 5 | 6 | using global::AutoFixture; 7 | 8 | [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false)] 9 | [SuppressMessage("Performance", "CA1813:Avoid unsealed attributes", Justification = "This attribute should be extendable by inheritance.")] 10 | public class CustomizeWithAttribute : CustomizeWithAttribute 11 | where T : ICustomization 12 | { 13 | [SuppressMessage("ReSharper", "MemberCanBeProtected.Global", Justification = "This attribute should be used directly.")] 14 | public CustomizeWithAttribute(params object[] args) 15 | : base(typeof(T), args) 16 | { 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.Core/Comparers/CustomizeAttributeComparer.cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.Core.Comparers 2 | { 3 | using System.Collections.Generic; 4 | 5 | using global::AutoFixture; 6 | 7 | internal class CustomizeAttributeComparer : Comparer 8 | where T : IParameterCustomizationSource 9 | { 10 | public override int Compare(IParameterCustomizationSource x, IParameterCustomizationSource y) 11 | { 12 | var isXFrozen = x is T; 13 | var isYFrozen = y is T; 14 | 15 | if (isXFrozen && !isYFrozen) 16 | { 17 | return 1; 18 | } 19 | 20 | if (isYFrozen && !isXFrozen) 21 | { 22 | return -1; 23 | } 24 | 25 | return 0; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /.github/workflows/fossa-scan.yml: -------------------------------------------------------------------------------- 1 | name: '🐯 FOSSA: License & security scan' 2 | 3 | on: 4 | pull_request: 5 | paths: 6 | - 'src/**' 7 | - '!src/qodana.yml' 8 | - '.github/workflows/fossa-scan.yml' 9 | types: [opened, synchronize, reopened] 10 | push: 11 | branches: 12 | - 'master' 13 | paths: 14 | - 'src/**' 15 | - '!src/qodana.yml' 16 | - '.github/workflows/fossa-scan.yml' 17 | workflow_dispatch: 18 | 19 | concurrency: 20 | group: ${{ github.workflow }}-${{ github.ref }} 21 | cancel-in-progress: true 22 | 23 | jobs: 24 | scan: 25 | runs-on: ubuntu-latest 26 | permissions: 27 | contents: read 28 | steps: 29 | - name: 📥 checkout 30 | uses: actions/checkout@v6 31 | with: 32 | fetch-depth: 0 33 | - name: 🔬 scan 34 | uses: fossas/fossa-action@main 35 | with: 36 | api-key: ${{ secrets.FOSSA_API_KEY }} 37 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.Core/Common/Check.cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.Core.Common 2 | { 3 | using System; 4 | using System.Diagnostics; 5 | 6 | using JetBrains.Annotations; 7 | 8 | /// 9 | /// Copied from Check.cs. 10 | /// 11 | [DebuggerStepThrough] 12 | public static class Check 13 | { 14 | [ContractAnnotation("value:null => halt")] 15 | public static T NotNull( 16 | [NoEnumeration][ValidatedNotNull] this T value, 17 | [InvokerParameterName][NotNull] string parameterName) 18 | { 19 | if (value is null) 20 | { 21 | throw new ArgumentNullException(parameterName); 22 | } 23 | 24 | return value; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.Core/Attributes/IgnoreVirtualMembersAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.Core.Attributes 2 | { 3 | using System; 4 | 5 | using global::AutoFixture; 6 | using global::AutoFixture.Xunit2; 7 | using Objectivity.AutoFixture.XUnit2.Core.Customizations; 8 | 9 | /// 10 | /// An attribute that can be applied to parameters in an -driven 11 | /// Theory to indicate that the parameter value should not have virtual properties populated 12 | /// when the creates an instance of that type. 13 | /// 14 | [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false)] 15 | public sealed class IgnoreVirtualMembersAttribute : CustomizeWithAttribute 16 | { 17 | public IgnoreVirtualMembersAttribute() 18 | { 19 | this.IncludeParameterType = true; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.Core/Customizations/IgnoreVirtualMembersCustomization.cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.Core.Customizations 2 | { 3 | using System; 4 | 5 | using global::AutoFixture; 6 | 7 | using Objectivity.AutoFixture.XUnit2.Core.Common; 8 | using Objectivity.AutoFixture.XUnit2.Core.SpecimenBuilders; 9 | 10 | public class IgnoreVirtualMembersCustomization : ICustomization 11 | { 12 | public IgnoreVirtualMembersCustomization() 13 | : this(null) 14 | { 15 | } 16 | 17 | public IgnoreVirtualMembersCustomization(Type reflectedType) 18 | { 19 | this.ReflectedType = reflectedType; 20 | } 21 | 22 | public Type ReflectedType { get; } 23 | 24 | public void Customize(IFixture fixture) 25 | { 26 | fixture.NotNull(nameof(fixture)).Customizations.Add(new IgnoreVirtualMembersSpecimenBuilder(this.ReflectedType)); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.Core/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | using System.Runtime.InteropServices; 3 | 4 | // Allow internals testing 5 | [assembly: InternalsVisibleTo("Objectivity.AutoFixture.XUnit2.Core.Tests, PublicKey=00240000048000009400000006020000002400005253413100040000010001007d78e6d8daff3a54f2992121ba90ece3d21507654f93c2b2e1f581c8694e90422b41d380ae82a5aac57f065cf3c96d69e1886a8e714497b686091bcfc8f62ed9687ccb4bdf9e2208b9c88a827def3f70d68d51ef47c0b7250ae9c88d5b05c65c451228247655b4ac019413df487fef931ddd860fb31407c9b26f3039bef789bc")] 6 | 7 | // Setting ComVisible to false makes the types in this assembly not visible 8 | // to COM components. If you need to access a type in this assembly from 9 | // COM, set the ComVisible attribute to true on that type. 10 | [assembly: ComVisible(false)] 11 | 12 | // The following GUID is for the ID of the typelib if this project is exposed to COM 13 | [assembly: Guid("6717bc95-f2d2-4eae-a680-d871d58a773b")] 14 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.AutoMoq/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | using System.Runtime.InteropServices; 3 | 4 | // Allow internals testing 5 | [assembly: InternalsVisibleTo("Objectivity.AutoFixture.XUnit2.AutoMoq.Tests, PublicKey=00240000048000009400000006020000002400005253413100040000010001007d78e6d8daff3a54f2992121ba90ece3d21507654f93c2b2e1f581c8694e90422b41d380ae82a5aac57f065cf3c96d69e1886a8e714497b686091bcfc8f62ed9687ccb4bdf9e2208b9c88a827def3f70d68d51ef47c0b7250ae9c88d5b05c65c451228247655b4ac019413df487fef931ddd860fb31407c9b26f3039bef789bc")] 6 | 7 | // Setting ComVisible to false makes the types in this assembly not visible 8 | // to COM components. If you need to access a type in this assembly from 9 | // COM, set the ComVisible attribute to true on that type. 10 | [assembly: ComVisible(false)] 11 | 12 | // The following GUID is for the ID of the typelib if this project is exposed to COM 13 | [assembly: Guid("08494845-cd20-4e6c-bd8f-63bd282fcb12")] 14 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.AutoFakeItEasy/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | using System.Runtime.InteropServices; 3 | 4 | // Allow internals testing 5 | [assembly: InternalsVisibleTo("Objectivity.AutoFixture.XUnit2.AutoFakeItEasy.Tests, PublicKey=00240000048000009400000006020000002400005253413100040000010001007d78e6d8daff3a54f2992121ba90ece3d21507654f93c2b2e1f581c8694e90422b41d380ae82a5aac57f065cf3c96d69e1886a8e714497b686091bcfc8f62ed9687ccb4bdf9e2208b9c88a827def3f70d68d51ef47c0b7250ae9c88d5b05c65c451228247655b4ac019413df487fef931ddd860fb31407c9b26f3039bef789bc")] 6 | 7 | // Setting ComVisible to false makes the types in this assembly not visible 8 | // to COM components. If you need to access a type in this assembly from 9 | // COM, set the ComVisible attribute to true on that type. 10 | [assembly: ComVisible(false)] 11 | 12 | // The following GUID is for the ID of the typelib if this project is exposed to COM 13 | [assembly: Guid("D4F6BF2B-D18E-4E99-9695-193C451C31BA")] 14 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.AutoNSubstitute/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | using System.Runtime.InteropServices; 3 | 4 | // Allow internals testing 5 | [assembly: InternalsVisibleTo("Objectivity.AutoFixture.XUnit2.AutoNSubstitute.Tests, PublicKey=00240000048000009400000006020000002400005253413100040000010001007d78e6d8daff3a54f2992121ba90ece3d21507654f93c2b2e1f581c8694e90422b41d380ae82a5aac57f065cf3c96d69e1886a8e714497b686091bcfc8f62ed9687ccb4bdf9e2208b9c88a827def3f70d68d51ef47c0b7250ae9c88d5b05c65c451228247655b4ac019413df487fef931ddd860fb31407c9b26f3039bef789bc")] 6 | 7 | // Setting ComVisible to false makes the types in this assembly not visible 8 | // to COM components. If you need to access a type in this assembly from 9 | // COM, set the ComVisible attribute to true on that type. 10 | [assembly: ComVisible(false)] 11 | 12 | // The following GUID is for the ID of the typelib if this project is exposed to COM 13 | [assembly: Guid("d3e477ea-f0a1-4287-a22d-c8d982231849")] 14 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.Core/Customizations/AutoDataCommonCustomization.cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.Core.Customizations 2 | { 3 | using global::AutoFixture; 4 | 5 | using Objectivity.AutoFixture.XUnit2.Core.Common; 6 | 7 | public class AutoDataCommonCustomization : ICustomization 8 | { 9 | public AutoDataCommonCustomization(bool ignoreVirtualMembers) 10 | { 11 | this.IgnoreVirtualMembers = ignoreVirtualMembers; 12 | } 13 | 14 | public bool IgnoreVirtualMembers { get; } 15 | 16 | public void Customize(IFixture fixture) 17 | { 18 | var adaptedFixture = fixture.NotNull(nameof(fixture)) 19 | .Customize(new DoNotThrowOnRecursionCustomization()) 20 | .Customize(new OmitOnRecursionCustomization()); 21 | 22 | if (this.IgnoreVirtualMembers) 23 | { 24 | adaptedFixture.Customize(new IgnoreVirtualMembersCustomization()); 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.Core.Tests/Customizations/OmitOnRecursionCustomizationTests.cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.Core.Tests.Customizations 2 | { 3 | using global::AutoFixture; 4 | using global::AutoFixture.Xunit2; 5 | using Objectivity.AutoFixture.XUnit2.Core.Customizations; 6 | 7 | using Xunit; 8 | 9 | [Collection("OmitOnRecursionCustomization")] 10 | [Trait("Category", "Customizations")] 11 | public class OmitOnRecursionCustomizationTests 12 | { 13 | [AutoData] 14 | [Theory(DisplayName = "GIVEN existing customization for fixture WHEN Customize is invoked THEN fixture should omit recursion")] 15 | public void GivenExistingCustomizationForFixture_WhenCustomizeIsInvoked_ThenFixtureShouldOmitRecursion(Fixture fixture, OmitOnRecursionCustomization customization) 16 | { 17 | // Arrange 18 | // Act 19 | fixture.Customize(customization); 20 | 21 | // Assert 22 | fixture.ShouldOmitRecursion(); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.Core.Tests/Customizations/DoNotThrowOnRecursionCustomizationTests.cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.Core.Tests.Customizations 2 | { 3 | using global::AutoFixture; 4 | using global::AutoFixture.Xunit2; 5 | using Objectivity.AutoFixture.XUnit2.Core.Customizations; 6 | 7 | using Xunit; 8 | 9 | [Collection("DoNotThrowOnRecursionCustomization")] 10 | [Trait("Category", "Customizations")] 11 | public class DoNotThrowOnRecursionCustomizationTests 12 | { 13 | [AutoData] 14 | [Theory(DisplayName = "GIVEN existing customization for fixture WHEN Customize is invoked THEN fixture should not throw on recursion")] 15 | public void GivenExistingCustomizationForFixture_WhenCustomizeIsInvoked_ThenFixtureShouldNotThrowOnRecursion(Fixture fixture, DoNotThrowOnRecursionCustomization customization) 16 | { 17 | // Arrange 18 | // Act 19 | fixture.Customize(customization); 20 | 21 | // Assert 22 | fixture.ShouldNotThrowOnRecursion(); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /.github/actions/materialize-signing-key/action.yml: -------------------------------------------------------------------------------- 1 | name: Materialize signing key 2 | description: Materializes key to sign assemblies 3 | inputs: 4 | signing-key-value: 5 | description: Value of the signing key 6 | required: true 7 | signing-key-file-name: 8 | description: Name of the signing key file 9 | required: false 10 | default: key.snk 11 | outputs: 12 | file-path: 13 | description: Signing key file path 14 | value: ${{ steps.signing-key.outputs.PATH }} 15 | runs: 16 | using: composite 17 | steps: 18 | - name: 🖊️ materialize signing key 19 | id: signing-key 20 | shell: pwsh 21 | run: | 22 | $ErrorActionPreference = 'stop' 23 | $path = [IO.Path]::Combine("${env:WORKING_DIRECTORY}","src","${env:SIGNING_KEY_FILE_NAME}") 24 | [IO.File]::WriteAllBytes($path, [Convert]::FromBase64String("${env:STRONG_NAME_KEY}")) 25 | "PATH=$path" >> $env:GITHUB_OUTPUT 26 | env: 27 | STRONG_NAME_KEY: ${{ inputs.signing-key-value }} 28 | SIGNING_KEY_FILE_NAME: ${{ inputs.signing-key-file-name }} 29 | WORKING_DIRECTORY: ${{ github.workspace }} 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Accenture 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.Core.Tests/Providers/AutoDataAttributeProviderTests.cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.Core.Tests.Providers 2 | { 3 | using global::AutoFixture; 4 | using global::AutoFixture.Xunit2; 5 | using Objectivity.AutoFixture.XUnit2.Core.Attributes; 6 | using Objectivity.AutoFixture.XUnit2.Core.Providers; 7 | 8 | using Xunit; 9 | 10 | [Collection("AutoDataAttributeProvider")] 11 | [Trait("Category", "Providers")] 12 | public class AutoDataAttributeProviderTests 13 | { 14 | [AutoData] 15 | [Theory(DisplayName = "GIVEN initialized fixture WHEN GetAttribute is invoked THEN attribute with specified fixture is returned")] 16 | public void GivenInitializedFixture_WhenGetAttributeIsInvoked_ThenAttributeWithSpecifiedFixtureIsReturned(Fixture fixture) 17 | { 18 | // Arrange 19 | var provider = new AutoDataAttributeProvider(); 20 | 21 | // Act 22 | var dataAttribute = provider.GetAttribute(fixture) as AutoDataAdapterAttribute; 23 | 24 | // Assert 25 | Assert.NotNull(dataAttribute); 26 | Assert.Equal(fixture, dataAttribute.AdaptedFixture); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.AutoMoq/Attributes/AutoMockDataAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.AutoMoq.Attributes 2 | { 3 | using System; 4 | 5 | using global::AutoFixture; 6 | using global::AutoFixture.AutoMoq; 7 | using Objectivity.AutoFixture.XUnit2.Core.Attributes; 8 | using Objectivity.AutoFixture.XUnit2.Core.Common; 9 | using Objectivity.AutoFixture.XUnit2.Core.Providers; 10 | 11 | using Xunit.Sdk; 12 | 13 | [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)] 14 | [DataDiscoverer("AutoFixture.Xunit2.NoPreDiscoveryDataDiscoverer", "AutoFixture.Xunit2")] 15 | public sealed class AutoMockDataAttribute : AutoDataBaseAttribute 16 | { 17 | public AutoMockDataAttribute() 18 | : this(new Fixture(), new AutoDataAttributeProvider()) 19 | { 20 | } 21 | 22 | public AutoMockDataAttribute(IFixture fixture, IAutoFixtureAttributeProvider provider) 23 | : base(fixture, provider) 24 | { 25 | } 26 | 27 | protected override IFixture Customize(IFixture fixture) 28 | { 29 | return fixture.NotNull(nameof(fixture)).Customize(new AutoMoqCustomization { ConfigureMembers = true }); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.AutoFakeItEasy/Attributes/AutoMockDataAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.AutoFakeItEasy.Attributes 2 | { 3 | using System; 4 | 5 | using global::AutoFixture; 6 | using global::AutoFixture.AutoFakeItEasy; 7 | using Objectivity.AutoFixture.XUnit2.Core.Attributes; 8 | using Objectivity.AutoFixture.XUnit2.Core.Common; 9 | using Objectivity.AutoFixture.XUnit2.Core.Providers; 10 | 11 | using Xunit.Sdk; 12 | 13 | [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)] 14 | [DataDiscoverer("AutoFixture.Xunit2.NoPreDiscoveryDataDiscoverer", "AutoFixture.Xunit2")] 15 | public sealed class AutoMockDataAttribute : AutoDataBaseAttribute 16 | { 17 | public AutoMockDataAttribute() 18 | : this(new Fixture(), new AutoDataAttributeProvider()) 19 | { 20 | } 21 | 22 | public AutoMockDataAttribute(IFixture fixture, IAutoFixtureAttributeProvider provider) 23 | : base(fixture, provider) 24 | { 25 | } 26 | 27 | protected override IFixture Customize(IFixture fixture) 28 | { 29 | return fixture.NotNull(nameof(fixture)).Customize(new AutoFakeItEasyCustomization { ConfigureMembers = true }); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.AutoNSubstitute/Attributes/AutoMockDataAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.AutoNSubstitute.Attributes 2 | { 3 | using System; 4 | 5 | using global::AutoFixture; 6 | using global::AutoFixture.AutoNSubstitute; 7 | using Objectivity.AutoFixture.XUnit2.Core.Attributes; 8 | using Objectivity.AutoFixture.XUnit2.Core.Common; 9 | using Objectivity.AutoFixture.XUnit2.Core.Providers; 10 | 11 | using Xunit.Sdk; 12 | 13 | [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)] 14 | [DataDiscoverer("AutoFixture.Xunit2.NoPreDiscoveryDataDiscoverer", "AutoFixture.Xunit2")] 15 | public sealed class AutoMockDataAttribute : AutoDataBaseAttribute 16 | { 17 | public AutoMockDataAttribute() 18 | : this(new Fixture(), new AutoDataAttributeProvider()) 19 | { 20 | } 21 | 22 | public AutoMockDataAttribute(IFixture fixture, IAutoFixtureAttributeProvider provider) 23 | : base(fixture, provider) 24 | { 25 | } 26 | 27 | protected override IFixture Customize(IFixture fixture) 28 | { 29 | return fixture.NotNull(nameof(fixture)).Customize(new AutoNSubstituteCustomization { ConfigureMembers = true }); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.Core/SpecimenBuilders/IgnoreVirtualMembersSpecimenBuilder.cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.Core.SpecimenBuilders 2 | { 3 | using System; 4 | using System.Reflection; 5 | using global::AutoFixture.Kernel; 6 | 7 | public class IgnoreVirtualMembersSpecimenBuilder : ISpecimenBuilder 8 | { 9 | public IgnoreVirtualMembersSpecimenBuilder() 10 | : this(null) 11 | { 12 | } 13 | 14 | public IgnoreVirtualMembersSpecimenBuilder(Type reflectedType) 15 | { 16 | this.ReflectedType = reflectedType; 17 | } 18 | 19 | public Type ReflectedType { get; } 20 | 21 | public object Create(object request, ISpecimenContext context) 22 | { 23 | if (request is PropertyInfo pi) //// is a property 24 | { 25 | if (this.ReflectedType is null //// is hosted anywhere 26 | || 27 | this.ReflectedType == pi.ReflectedType) //// is hosted in defined type 28 | { 29 | if (pi.GetGetMethod().IsVirtual) 30 | { 31 | return new OmitSpecimen(); 32 | } 33 | } 34 | } 35 | 36 | return new NoSpecimen(); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.Core/Attributes/PickNegativeAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.Core.Attributes 2 | { 3 | using System; 4 | using System.Reflection; 5 | 6 | using global::AutoFixture; 7 | using global::AutoFixture.Kernel; 8 | using global::AutoFixture.Xunit2; 9 | using Objectivity.AutoFixture.XUnit2.Core.Factories; 10 | using Objectivity.AutoFixture.XUnit2.Core.SpecimenBuilders; 11 | 12 | [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false)] 13 | public sealed class PickNegativeAttribute : CustomizeAttribute 14 | { 15 | private readonly IFactory negativeValuesRequestFactory = new NegativeValuesRequestFactory(); 16 | 17 | public override ICustomization GetCustomization(ParameterInfo parameter) 18 | { 19 | if (parameter is null) 20 | { 21 | throw new ArgumentNullException(nameof(parameter)); 22 | } 23 | 24 | return new CompositeSpecimenBuilder( 25 | new FilteringSpecimenBuilder( 26 | new RequestFactoryRelay(this.negativeValuesRequestFactory.Create), 27 | new EqualRequestSpecification(parameter)), 28 | new RandomFixedValuesGenerator()) 29 | .ToCustomization(); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.AutoMoq/Attributes/InlineAutoMockDataAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.AutoMoq.Attributes 2 | { 3 | using System; 4 | 5 | using global::AutoFixture; 6 | using global::AutoFixture.AutoMoq; 7 | using Objectivity.AutoFixture.XUnit2.Core.Attributes; 8 | using Objectivity.AutoFixture.XUnit2.Core.Common; 9 | using Objectivity.AutoFixture.XUnit2.Core.Providers; 10 | 11 | using Xunit.Sdk; 12 | 13 | [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] 14 | [DataDiscoverer("AutoFixture.Xunit2.NoPreDiscoveryDataDiscoverer", "AutoFixture.Xunit2")] 15 | public sealed class InlineAutoMockDataAttribute : InlineAutoDataBaseAttribute 16 | { 17 | public InlineAutoMockDataAttribute(params object[] values) 18 | : this(new Fixture(), new InlineAutoDataAttributeProvider(), values) 19 | { 20 | } 21 | 22 | public InlineAutoMockDataAttribute(IFixture fixture, IAutoFixtureInlineAttributeProvider provider, params object[] values) 23 | : base(fixture, provider, values) 24 | { 25 | } 26 | 27 | protected override IFixture Customize(IFixture fixture) 28 | { 29 | return fixture.NotNull(nameof(fixture)).Customize(new AutoMoqCustomization { ConfigureMembers = true }); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.AutoFakeItEasy/Attributes/InlineAutoMockDataAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.AutoFakeItEasy.Attributes 2 | { 3 | using System; 4 | 5 | using global::AutoFixture; 6 | using global::AutoFixture.AutoFakeItEasy; 7 | using Objectivity.AutoFixture.XUnit2.Core.Attributes; 8 | using Objectivity.AutoFixture.XUnit2.Core.Common; 9 | using Objectivity.AutoFixture.XUnit2.Core.Providers; 10 | 11 | using Xunit.Sdk; 12 | 13 | [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] 14 | [DataDiscoverer("AutoFixture.Xunit2.NoPreDiscoveryDataDiscoverer", "AutoFixture.Xunit2")] 15 | public sealed class InlineAutoMockDataAttribute : InlineAutoDataBaseAttribute 16 | { 17 | public InlineAutoMockDataAttribute(params object[] values) 18 | : this(new Fixture(), new InlineAutoDataAttributeProvider(), values) 19 | { 20 | } 21 | 22 | public InlineAutoMockDataAttribute(IFixture fixture, IAutoFixtureInlineAttributeProvider provider, params object[] values) 23 | : base(fixture, provider, values) 24 | { 25 | } 26 | 27 | protected override IFixture Customize(IFixture fixture) 28 | { 29 | return fixture.NotNull(nameof(fixture)).Customize(new AutoFakeItEasyCustomization { ConfigureMembers = true }); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.AutoNSubstitute/Attributes/InlineAutoMockDataAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.AutoNSubstitute.Attributes 2 | { 3 | using System; 4 | 5 | using global::AutoFixture; 6 | using global::AutoFixture.AutoNSubstitute; 7 | using Objectivity.AutoFixture.XUnit2.Core.Attributes; 8 | using Objectivity.AutoFixture.XUnit2.Core.Common; 9 | using Objectivity.AutoFixture.XUnit2.Core.Providers; 10 | 11 | using Xunit.Sdk; 12 | 13 | [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] 14 | [DataDiscoverer("AutoFixture.Xunit2.NoPreDiscoveryDataDiscoverer", "AutoFixture.Xunit2")] 15 | public sealed class InlineAutoMockDataAttribute : InlineAutoDataBaseAttribute 16 | { 17 | public InlineAutoMockDataAttribute(params object[] values) 18 | : this(new Fixture(), new InlineAutoDataAttributeProvider(), values) 19 | { 20 | } 21 | 22 | public InlineAutoMockDataAttribute(IFixture fixture, IAutoFixtureInlineAttributeProvider provider, params object[] values) 23 | : base(fixture, provider, values) 24 | { 25 | } 26 | 27 | protected override IFixture Customize(IFixture fixture) 28 | { 29 | return fixture.NotNull(nameof(fixture)).Customize(new AutoNSubstituteCustomization { ConfigureMembers = true }); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.Core.Tests/Providers/InlineAutoDataAttributeProviderTests.cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.Core.Tests.Providers 2 | { 3 | using global::AutoFixture; 4 | using global::AutoFixture.Xunit2; 5 | using Objectivity.AutoFixture.XUnit2.Core.Attributes; 6 | using Objectivity.AutoFixture.XUnit2.Core.Providers; 7 | 8 | using Xunit; 9 | 10 | [Collection("InlineAutoDataAttributeProvider")] 11 | [Trait("Category", "Providers")] 12 | public class InlineAutoDataAttributeProviderTests 13 | { 14 | [AutoData] 15 | [Theory(DisplayName = "GIVEN initialized fixture WHEN GetAttribute is invoked THEN attribute with specified fixture is returned")] 16 | public void GivenInitializedFixture_WhenGetAttributeIsInvoked_ThenAttributeWithSpecifiedFixtureIsReturned( 17 | Fixture fixture, 18 | object[] inlineValues) 19 | { 20 | // Arrange 21 | var provider = new InlineAutoDataAttributeProvider(); 22 | 23 | // Act 24 | var attribute = provider.GetAttribute(fixture, inlineValues); 25 | 26 | // Assert 27 | var autoDataAdapterAttribute = Assert.IsType(attribute); 28 | Assert.Equal(fixture, autoDataAdapterAttribute.AdaptedFixture); 29 | Assert.Equal(inlineValues, autoDataAdapterAttribute.InlineValues); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /.github/workflows/tag.yml: -------------------------------------------------------------------------------- 1 | name: '🏷️ Add tag to repository' 2 | 3 | on: 4 | workflow_call: 5 | inputs: 6 | version: 7 | description: Assembly and package version 8 | required: true 9 | type: string 10 | 11 | defaults: 12 | run: 13 | shell: pwsh 14 | 15 | jobs: 16 | run: 17 | runs-on: ubuntu-latest 18 | timeout-minutes: 15 19 | permissions: 20 | contents: write 21 | steps: 22 | - name: 📥 checkout 23 | uses: actions/checkout@v6 24 | with: 25 | fetch-depth: 0 26 | - name: 🏷️ tag version 27 | run: | 28 | $ErrorActionPreference = 'stop' 29 | $semanticVersionFormat = '^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$' 30 | if ($env:PACKAGE_VERSION -notmatch $semanticVersionFormat) { 31 | throw "Invalid version format: $($env:PACKAGE_VERSION). Expected format should follow Semantic Versioning 2.0.0 (https://semver.org/)." 32 | } 33 | 34 | git tag "${env:PACKAGE_VERSION}" 35 | if ($LastExitCode -ne 0) { 36 | throw "git tag failed with exit code $LastExitCode" 37 | } 38 | 39 | git push origin "${env:PACKAGE_VERSION}" 40 | if ($LastExitCode -ne 0) { 41 | throw "git push failed with exit code $LastExitCode" 42 | } 43 | env: 44 | PACKAGE_VERSION: ${{ inputs.version }} 45 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: '📤 Publish NuGet packages' 2 | 3 | on: 4 | workflow_call: 5 | inputs: 6 | environment: 7 | description: Name of environment 8 | type: string 9 | required: true 10 | default: prod 11 | 12 | env: 13 | DOTNET_NOLOGO: true 14 | DOTNET_CLI_TELEMETRY_OPTOUT: true 15 | 16 | defaults: 17 | run: 18 | shell: pwsh 19 | 20 | jobs: 21 | run: 22 | runs-on: ubuntu-latest 23 | timeout-minutes: 15 24 | permissions: 25 | packages: write 26 | environment: 27 | name: ${{ inputs.environment }} 28 | strategy: 29 | matrix: 30 | packageSource: 31 | - { url: 'https://api.nuget.org/v3/index.json', apiKeySecretName: 'NUGET_API_KEY' } 32 | - { url: 'https://nuget.pkg.github.com/Accenture/index.json', apiKeySecretName: 'GITHUB_TOKEN' } 33 | steps: 34 | - name: 🔽 download packages 35 | uses: actions/download-artifact@v7 36 | with: 37 | pattern: packages-* 38 | merge-multiple: true 39 | - name: 📤 push 40 | run: | 41 | $ErrorActionPreference = 'stop' 42 | dotnet nuget push **/*.nupkg --api-key ${env:API_KEY} --source "${env:PACKAGE_SOURCE_URL}" --skip-duplicate 43 | if ($LastExitCode -ne 0) { 44 | throw "dotnet nuget push failed with exit code $LastExitCode" 45 | } 46 | env: 47 | API_KEY: ${{ secrets[matrix.packageSource.apiKeySecretName] }} 48 | PACKAGE_SOURCE_URL: ${{ matrix.packageSource.url }} 49 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.AutoMoq/Attributes/MemberAutoMockDataAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.AutoMoq.Attributes 2 | { 3 | using System; 4 | 5 | using global::AutoFixture; 6 | using global::AutoFixture.AutoMoq; 7 | using Objectivity.AutoFixture.XUnit2.Core.Attributes; 8 | using Objectivity.AutoFixture.XUnit2.Core.Common; 9 | using Objectivity.AutoFixture.XUnit2.Core.Providers; 10 | 11 | using Xunit.Sdk; 12 | 13 | [AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = true)] 14 | [DataDiscoverer("AutoFixture.Xunit2.NoPreDiscoveryDataDiscoverer", "AutoFixture.Xunit2")] 15 | public sealed class MemberAutoMockDataAttribute : MemberAutoDataBaseAttribute 16 | { 17 | public MemberAutoMockDataAttribute(string memberName, params object[] parameters) 18 | : this(new Fixture(), memberName, parameters) 19 | { 20 | } 21 | 22 | public MemberAutoMockDataAttribute(IFixture fixture, string memberName, params object[] parameters) 23 | : base(fixture, memberName, parameters) 24 | { 25 | } 26 | 27 | protected override IAutoFixtureInlineAttributeProvider CreateProvider() 28 | { 29 | return new InlineAutoDataAttributeProvider(); 30 | } 31 | 32 | protected override IFixture Customize(IFixture fixture) 33 | { 34 | return fixture.NotNull(nameof(fixture)).Customize(new AutoMoqCustomization { ConfigureMembers = true }); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.AutoFakeItEasy/Attributes/MemberAutoMockDataAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.AutoFakeItEasy.Attributes 2 | { 3 | using System; 4 | 5 | using global::AutoFixture; 6 | using global::AutoFixture.AutoFakeItEasy; 7 | using Objectivity.AutoFixture.XUnit2.Core.Attributes; 8 | using Objectivity.AutoFixture.XUnit2.Core.Common; 9 | using Objectivity.AutoFixture.XUnit2.Core.Providers; 10 | 11 | using Xunit.Sdk; 12 | 13 | [AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = true)] 14 | [DataDiscoverer("AutoFixture.Xunit2.NoPreDiscoveryDataDiscoverer", "AutoFixture.Xunit2")] 15 | public sealed class MemberAutoMockDataAttribute : MemberAutoDataBaseAttribute 16 | { 17 | public MemberAutoMockDataAttribute(string memberName, params object[] parameters) 18 | : this(new Fixture(), memberName, parameters) 19 | { 20 | } 21 | 22 | public MemberAutoMockDataAttribute(IFixture fixture, string memberName, params object[] parameters) 23 | : base(fixture, memberName, parameters) 24 | { 25 | } 26 | 27 | protected override IAutoFixtureInlineAttributeProvider CreateProvider() 28 | { 29 | return new InlineAutoDataAttributeProvider(); 30 | } 31 | 32 | protected override IFixture Customize(IFixture fixture) 33 | { 34 | return fixture.NotNull(nameof(fixture)).Customize(new AutoFakeItEasyCustomization { ConfigureMembers = true }); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.AutoNSubstitute/Attributes/MemberAutoMockDataAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.AutoNSubstitute.Attributes 2 | { 3 | using System; 4 | 5 | using global::AutoFixture; 6 | using global::AutoFixture.AutoNSubstitute; 7 | using Objectivity.AutoFixture.XUnit2.Core.Attributes; 8 | using Objectivity.AutoFixture.XUnit2.Core.Common; 9 | using Objectivity.AutoFixture.XUnit2.Core.Providers; 10 | 11 | using Xunit.Sdk; 12 | 13 | [AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = true)] 14 | [DataDiscoverer("AutoFixture.Xunit2.NoPreDiscoveryDataDiscoverer", "AutoFixture.Xunit2")] 15 | public sealed class MemberAutoMockDataAttribute : MemberAutoDataBaseAttribute 16 | { 17 | public MemberAutoMockDataAttribute(string memberName, params object[] parameters) 18 | : this(new Fixture(), memberName, parameters) 19 | { 20 | } 21 | 22 | public MemberAutoMockDataAttribute(IFixture fixture, string memberName, params object[] parameters) 23 | : base(fixture, memberName, parameters) 24 | { 25 | } 26 | 27 | protected override IAutoFixtureInlineAttributeProvider CreateProvider() 28 | { 29 | return new InlineAutoDataAttributeProvider(); 30 | } 31 | 32 | protected override IFixture Customize(IFixture fixture) 33 | { 34 | return fixture.NotNull(nameof(fixture)).Customize(new AutoNSubstituteCustomization { ConfigureMembers = true }); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.AutoMoq.Tests/.editorconfig: -------------------------------------------------------------------------------- 1 | root = false 2 | 3 | [*.cs] 4 | 5 | # CA1062: Validate arguments of public methods 6 | dotnet_diagnostic.CA1062.severity = none 7 | # CA1506: Avoid excessive class coupling 8 | dotnet_diagnostic.CA1506.severity = none 9 | # CA1515: Consider making public types internal 10 | dotnet_diagnostic.CA1515.severity = none 11 | # CA1707: Identifiers should not contain underscores 12 | dotnet_diagnostic.CA1707.severity = none 13 | # CA1822: Mark members as static 14 | dotnet_diagnostic.CA1822.severity = none 15 | # CA2000: Dispose objects before losing scope 16 | dotnet_diagnostic.CA2000.severity = none 17 | # CA2007: Consider calling ConfigureAwait on the awaited task 18 | dotnet_diagnostic.CA2007.severity = none 19 | # RCS1090: Call 'ConfigureAwait(false)'. 20 | dotnet_diagnostic.RCS1090.severity = none 21 | # S3376: Attribute, EventArgs, and Exception type names should end with the type being extended. 22 | dotnet_diagnostic.S3376.severity = none 23 | # S4158: Empty collections should not be accessed or iterated. 24 | dotnet_diagnostic.S4158.severity = none 25 | # S6608: Prefer indexing instead of "Enumerable" methods on types implementing "IList" 26 | dotnet_diagnostic.S6608.severity = none 27 | 28 | ## ReSharper 29 | 30 | # Possible 'System.NullReferenceException' 31 | resharper_possible_null_reference_exception_highlighting = none 32 | # Use collection expression syntax 33 | resharper_use_collection_expression_highlighting = none 34 | # Possible 'null' assignment to entity 35 | resharper_assign_null_to_not_null_attribute_highlighting = none -------------------------------------------------------------------------------- /.github/workflows/semgrep.yml: -------------------------------------------------------------------------------- 1 | name: '🔎 Semgrep: Static Code Analysis' 2 | 3 | on: 4 | pull_request: 5 | paths: 6 | - 'src/**' 7 | - '!src/qodana.yml' 8 | - '.github/workflows/semgrep.yml' 9 | types: [opened, synchronize, reopened] 10 | push: 11 | branches: 12 | - 'master' 13 | paths: 14 | - 'src/**' 15 | - '!src/qodana.yml' 16 | - '.github/workflows/semgrep.yml' 17 | schedule: 18 | - cron: '38 7 * * 0' # Random time 19 | workflow_dispatch: 20 | 21 | defaults: 22 | run: 23 | shell: bash 24 | 25 | concurrency: 26 | group: ${{ github.workflow }}-${{ github.ref }} 27 | cancel-in-progress: true 28 | 29 | jobs: 30 | scan: 31 | # Skip any PR created by dependabot to avoid permission issues: 32 | if: ${{ github.actor != 'dependabot[bot]' }} 33 | runs-on: ubuntu-latest 34 | permissions: 35 | contents: write 36 | checks: write 37 | security-events: write 38 | container: 39 | # A Docker image with Semgrep installed. Do not change this. 40 | image: semgrep/semgrep 41 | steps: 42 | - name: 📥 checkout 43 | uses: actions/checkout@v6 44 | with: 45 | fetch-depth: 0 46 | - name: 🔬 semgrep scan 47 | run: semgrep ci --sarif > semgrep.sarif 48 | env: 49 | SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN }} 50 | - name: 📊 upload sarif file for GitHub Advanced Security Dashboard 51 | uses: github/codeql-action/upload-sarif@v4 52 | with: 53 | sarif_file: semgrep.sarif 54 | if: ${{ always() }} 55 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.AutoFakeItEasy.Tests/.editorconfig: -------------------------------------------------------------------------------- 1 | root = false 2 | 3 | [*.cs] 4 | 5 | # CA1062: Validate arguments of public methods 6 | dotnet_diagnostic.CA1062.severity = none 7 | # CA1506: Avoid excessive class coupling 8 | dotnet_diagnostic.CA1506.severity = none 9 | # CA1515: Consider making public types internal 10 | dotnet_diagnostic.CA1515.severity = none 11 | # CA1707: Identifiers should not contain underscores 12 | dotnet_diagnostic.CA1707.severity = none 13 | # CA1822: Mark members as static 14 | dotnet_diagnostic.CA1822.severity = none 15 | # CA2000: Dispose objects before losing scope 16 | dotnet_diagnostic.CA2000.severity = none 17 | # CA2007: Consider calling ConfigureAwait on the awaited task 18 | dotnet_diagnostic.CA2007.severity = none 19 | # RCS1090: Call 'ConfigureAwait(false)'. 20 | dotnet_diagnostic.RCS1090.severity = none 21 | # S3376: Attribute, EventArgs, and Exception type names should end with the type being extended. 22 | dotnet_diagnostic.S3376.severity = none 23 | # S4158: Empty collections should not be accessed or iterated. 24 | dotnet_diagnostic.S4158.severity = none 25 | # S6608: Prefer indexing instead of "Enumerable" methods on types implementing "IList" 26 | dotnet_diagnostic.S6608.severity = none 27 | 28 | ## ReSharper 29 | 30 | # Possible 'System.NullReferenceException' 31 | resharper_possible_null_reference_exception_highlighting = none 32 | # Use collection expression syntax 33 | resharper_use_collection_expression_highlighting = none 34 | # Possible 'null' assignment to entity 35 | resharper_assign_null_to_not_null_attribute_highlighting = none -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.AutoNSubstitute.Tests/.editorconfig: -------------------------------------------------------------------------------- 1 | root = false 2 | 3 | [*.cs] 4 | 5 | # CA1062: Validate arguments of public methods 6 | dotnet_diagnostic.CA1062.severity = none 7 | # CA1506: Avoid excessive class coupling 8 | dotnet_diagnostic.CA1506.severity = none 9 | # CA1515: Consider making public types internal 10 | dotnet_diagnostic.CA1515.severity = none 11 | # CA1707: Identifiers should not contain underscores 12 | dotnet_diagnostic.CA1707.severity = none 13 | # CA1822: Mark members as static 14 | dotnet_diagnostic.CA1822.severity = none 15 | # CA2000: Dispose objects before losing scope 16 | dotnet_diagnostic.CA2000.severity = none 17 | # CA2007: Consider calling ConfigureAwait on the awaited task 18 | dotnet_diagnostic.CA2007.severity = none 19 | # RCS1090: Call 'ConfigureAwait(false)'. 20 | dotnet_diagnostic.RCS1090.severity = none 21 | # S3376: Attribute, EventArgs, and Exception type names should end with the type being extended. 22 | dotnet_diagnostic.S3376.severity = none 23 | # S4158: Empty collections should not be accessed or iterated. 24 | dotnet_diagnostic.S4158.severity = none 25 | # S6608: Prefer indexing instead of "Enumerable" methods on types implementing "IList" 26 | dotnet_diagnostic.S6608.severity = none 27 | 28 | ## ReSharper 29 | 30 | # Possible 'System.NullReferenceException' 31 | resharper_possible_null_reference_exception_highlighting = none 32 | # Use collection expression syntax 33 | resharper_use_collection_expression_highlighting = none 34 | # Possible 'null' assignment to entity 35 | resharper_assign_null_to_not_null_attribute_highlighting = none -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.Core/MemberData/MemberAutoDataItemExtender.cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.Core.MemberData 2 | { 3 | using System.Diagnostics.CodeAnalysis; 4 | using System.Linq; 5 | using System.Reflection; 6 | 7 | using global::AutoFixture; 8 | 9 | using Objectivity.AutoFixture.XUnit2.Core.Common; 10 | using Objectivity.AutoFixture.XUnit2.Core.Providers; 11 | 12 | internal class MemberAutoDataItemExtender : IDataItemExtender 13 | { 14 | public MemberAutoDataItemExtender(IFixture fixture, IAutoFixtureInlineAttributeProvider dataAttributeProvider) 15 | { 16 | this.Fixture = fixture.NotNull(nameof(fixture)); 17 | this.DataAttributeProvider = dataAttributeProvider.NotNull(nameof(dataAttributeProvider)); 18 | } 19 | 20 | [SuppressMessage("ReSharper", "MemberCanBePrivate.Global", Justification = "Testable design.")] 21 | public IFixture Fixture { get; } 22 | 23 | [SuppressMessage("ReSharper", "MemberCanBePrivate.Global", Justification = "Testable design.")] 24 | public IAutoFixtureInlineAttributeProvider DataAttributeProvider { get; } 25 | 26 | public object[] Extend(MethodInfo testMethod, object[] values) 27 | { 28 | if (values is null) 29 | { 30 | return null; 31 | } 32 | 33 | var method = testMethod.NotNull(nameof(testMethod)); 34 | var dataAttribute = this.DataAttributeProvider.GetAttribute(this.Fixture, values); 35 | 36 | return dataAttribute.GetData(method).FirstOrDefault(); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.Core.Tests/Common/CheckTests.cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.Core.Tests.Common 2 | { 3 | using System; 4 | using System.Diagnostics.CodeAnalysis; 5 | 6 | using Objectivity.AutoFixture.XUnit2.Core.Common; 7 | 8 | using Xunit; 9 | 10 | [Collection("Check")] 11 | [Trait("Category", "Common")] 12 | [SuppressMessage("ReSharper", "NotResolvedInText", Justification = "Used for testing only.")] 13 | public class CheckTests 14 | { 15 | [Fact(DisplayName = "GIVEN uninitialized object WHEN NotNull is invoked THEN exception is thrown")] 16 | public void GivenUninitializedObject_WhenNotNullIsInvoked_ThenExceptionIsThrown() 17 | { 18 | // Arrange 19 | const object value = null; 20 | const string expectedParameterName = "value"; 21 | 22 | // Act 23 | static object Act() => value.NotNull(expectedParameterName); 24 | 25 | // Assert 26 | var exception = Assert.Throws(Act); 27 | Assert.Equal(expectedParameterName, exception.ParamName); 28 | } 29 | 30 | [Fact(DisplayName = "GIVEN initialized object WHEN NotNull is invoked THEN the same object is returned")] 31 | public void GivenInitializedObject_WhenNotNullIsInvoked_ThenTheSameObjectIsReturned() 32 | { 33 | // Arrange 34 | var value = new object(); 35 | 36 | // Act 37 | var result = value.NotNull("value"); 38 | 39 | // Assert 40 | Assert.Equal(value, result); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /.github/workflows/codeql.yml: -------------------------------------------------------------------------------- 1 | name: '🔬 CodeQL: Semantic code analysis' 2 | 3 | on: 4 | pull_request: 5 | paths: 6 | - 'src/**' 7 | - '!src/qodana.yml' 8 | - '.github/workflows/codeql.yml' 9 | types: [opened, synchronize, reopened] 10 | push: 11 | branches: 12 | - 'master' 13 | paths: 14 | - 'src/**' 15 | - '!src/qodana.yml' 16 | - '.github/workflows/codeql.yml' 17 | schedule: 18 | - cron: '20 23 * * 0' 19 | workflow_dispatch: 20 | 21 | env: 22 | DOTNET_NOLOGO: true 23 | DOTNET_CLI_TELEMETRY_OPTOUT: true 24 | Configuration: Release 25 | 26 | defaults: 27 | run: 28 | shell: pwsh 29 | 30 | concurrency: 31 | group: ${{ github.workflow }}-${{ github.ref }} 32 | cancel-in-progress: true 33 | 34 | jobs: 35 | scan: 36 | runs-on: ubuntu-latest 37 | timeout-minutes: 360 38 | permissions: 39 | actions: read 40 | contents: read 41 | security-events: write 42 | 43 | strategy: 44 | fail-fast: false 45 | matrix: 46 | language: [ 'csharp' ] 47 | 48 | steps: 49 | - name: 📥 checkout 50 | uses: actions/checkout@v6 51 | with: 52 | fetch-depth: 0 53 | - name: 🎰 initialize CodeQL 54 | uses: github/codeql-action/init@v4 55 | with: 56 | languages: ${{ matrix.language }} 57 | - name: 🏗️ build 58 | run: | 59 | $ErrorActionPreference = 'stop' 60 | dotnet build ./src/Objectivity.AutoFixture.XUnit2.AutoMock.sln 61 | if ($LastExitCode -ne 0) { 62 | throw "dotnet build failed with exit code $LastExitCode" 63 | } 64 | - name: 🔬 analyze with CodeQL 65 | uses: github/codeql-action/analyze@v4 66 | with: 67 | category: '/language:${{ matrix.language }}' 68 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.Core.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.7.34202.233 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Objectivity.AutoFixture.XUnit2.Core", "Objectivity.AutoFixture.XUnit2.Core\Objectivity.AutoFixture.XUnit2.Core.csproj", "{A639D1F4-C3D5-499F-944B-DEE361C20082}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Objectivity.AutoFixture.XUnit2.Core.Tests", "Objectivity.AutoFixture.XUnit2.Core.Tests\Objectivity.AutoFixture.XUnit2.Core.Tests.csproj", "{D9095A71-49FC-47FE-8C49-1677EBE42B53}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Release|Any CPU = Release|Any CPU 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {A639D1F4-C3D5-499F-944B-DEE361C20082}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {A639D1F4-C3D5-499F-944B-DEE361C20082}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {A639D1F4-C3D5-499F-944B-DEE361C20082}.Release|Any CPU.ActiveCfg = Release|Any CPU 19 | {A639D1F4-C3D5-499F-944B-DEE361C20082}.Release|Any CPU.Build.0 = Release|Any CPU 20 | {D9095A71-49FC-47FE-8C49-1677EBE42B53}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {D9095A71-49FC-47FE-8C49-1677EBE42B53}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {D9095A71-49FC-47FE-8C49-1677EBE42B53}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {D9095A71-49FC-47FE-8C49-1677EBE42B53}.Release|Any CPU.Build.0 = Release|Any CPU 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {D092E697-BEB8-4A00-B37E-4109FD2B17E7} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.Core/SpecimenBuilders/RandomExceptValuesGenerator.cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.Core.SpecimenBuilders 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Diagnostics.CodeAnalysis; 6 | using System.Linq; 7 | 8 | using global::AutoFixture; 9 | using global::AutoFixture.Kernel; 10 | using Objectivity.AutoFixture.XUnit2.Core.Common; 11 | using Objectivity.AutoFixture.XUnit2.Core.Requests; 12 | 13 | internal class RandomExceptValuesGenerator : ISpecimenBuilder 14 | { 15 | [SuppressMessage("Major Bug", "S2583:Conditionally executed code should be reachable", Justification = "Analyzer issue as the code is reachable")] 16 | public object Create(object request, ISpecimenContext context) 17 | { 18 | if (context is null) 19 | { 20 | throw new ArgumentNullException(nameof(context)); 21 | } 22 | 23 | if (request.NotNull(nameof(request)) is ExceptValuesRequest exceptValuesRequest) 24 | { 25 | var duplicateLimiter = new HashSet(); 26 | object result; 27 | 28 | do 29 | { 30 | result = context.Resolve(exceptValuesRequest.OperandType); 31 | var hasDuplicate = duplicateLimiter.Contains(result); 32 | if (hasDuplicate) 33 | { 34 | throw new ObjectCreationException("The value could not be created. Probably all possible values were excluded."); 35 | } 36 | 37 | duplicateLimiter.Add(result); 38 | } 39 | while (exceptValuesRequest.Values.Contains(result)); 40 | 41 | return result; 42 | } 43 | 44 | return new NoSpecimen(); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.Core.Tests/Comparers/CustomizeAttributeComparerTests.cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.Core.Tests.Comparers 2 | { 3 | using global::AutoFixture; 4 | using global::AutoFixture.Xunit2; 5 | using Objectivity.AutoFixture.XUnit2.Core.Attributes; 6 | using Objectivity.AutoFixture.XUnit2.Core.Comparers; 7 | using Objectivity.AutoFixture.XUnit2.Core.Customizations; 8 | 9 | using Xunit; 10 | 11 | [Collection("CustomizeAttributeComparer")] 12 | [Trait("Category", "Comparers")] 13 | public class CustomizeAttributeComparerTests 14 | { 15 | private static readonly CustomizeAttributeComparer Comparer = new(); 16 | private static readonly CustomizeWithAttribute CustomizeAttribute = new(typeof(DoNotThrowOnRecursionCustomization)); 17 | private static readonly FrozenAttribute FrozenAttribute = new(); 18 | 19 | public static TheoryData TestData { get; } = new() 20 | { 21 | { CustomizeAttribute, CustomizeAttribute, 0 }, 22 | { FrozenAttribute, FrozenAttribute, 0 }, 23 | { FrozenAttribute, CustomizeAttribute, 1 }, 24 | { CustomizeAttribute, FrozenAttribute, -1 }, 25 | }; 26 | 27 | [MemberData(nameof(TestData))] 28 | [Theory(DisplayName = "GIVEN both attributes WHEN Compare is invoked THEN expected result returned")] 29 | public void GivenBothNonFrozenAttributes_WhenCompareIsInvoked_ThenBothEquals( 30 | IParameterCustomizationSource x, 31 | IParameterCustomizationSource y, 32 | int expectedResult) 33 | { 34 | // Arrange 35 | // Act 36 | var result = Comparer.Compare(x, y); 37 | 38 | // Assert 39 | Assert.Equal(expectedResult, result); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.Core/Attributes/AutoDataBaseAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.Core.Attributes 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Diagnostics.CodeAnalysis; 6 | using System.Reflection; 7 | 8 | using global::AutoFixture; 9 | 10 | using Objectivity.AutoFixture.XUnit2.Core.Common; 11 | using Objectivity.AutoFixture.XUnit2.Core.Customizations; 12 | using Objectivity.AutoFixture.XUnit2.Core.Providers; 13 | 14 | using Xunit.Sdk; 15 | 16 | [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)] 17 | public abstract class AutoDataBaseAttribute : DataAttribute 18 | { 19 | protected AutoDataBaseAttribute(IFixture fixture, IAutoFixtureAttributeProvider provider) 20 | { 21 | this.Fixture = fixture.NotNull(nameof(fixture)); 22 | this.Provider = provider.NotNull(nameof(provider)); 23 | } 24 | 25 | public IFixture Fixture { get; } 26 | 27 | /// 28 | /// Gets or sets a value indicating whether virtual members should be ignored during object creation. 29 | /// 30 | /// Indicates whether virtual members should be ignored during object creation. 31 | public bool IgnoreVirtualMembers { get; set; } 32 | 33 | public IAutoFixtureAttributeProvider Provider { get; } 34 | 35 | public override IEnumerable GetData(MethodInfo testMethod) 36 | { 37 | this.Fixture.Customize(new AutoDataCommonCustomization(this.IgnoreVirtualMembers)); 38 | this.Customize(this.Fixture); 39 | 40 | return this.Provider.GetAttribute(this.Fixture).GetData(testMethod); 41 | } 42 | 43 | [SuppressMessage("ReSharper", "UnusedMethodReturnValue.Global", Justification = "Align design with AutoFixture.")] 44 | protected abstract IFixture Customize(IFixture fixture); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.Core/Common/RoundRobinEnumerable[T].cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.Core.Common 2 | { 3 | using System; 4 | using System.Collections; 5 | using System.Diagnostics.CodeAnalysis; 6 | 7 | [SuppressMessage("Design", "CA1010:Generic interface should also be implemented", Justification = "It is not necessary for internal design.")] 8 | internal sealed class RoundRobinEnumerable : IEnumerator 9 | { 10 | private const int InitialPosition = -1; 11 | private const int FirstElementPosition = 0; 12 | 13 | private readonly T[] values; 14 | private readonly int maxPosition; 15 | private int position = InitialPosition; 16 | 17 | public RoundRobinEnumerable(params T[] values) 18 | { 19 | this.values = values.NotNull(nameof(values)); 20 | if (values.Length == 0) 21 | { 22 | throw new ArgumentException("At least one value is expected to be specified.", nameof(values)); 23 | } 24 | 25 | this.maxPosition = values.Length - 1; 26 | } 27 | 28 | public T Current 29 | { 30 | get 31 | { 32 | try 33 | { 34 | return this.values[this.position]; 35 | } 36 | catch (IndexOutOfRangeException) 37 | { 38 | throw new InvalidOperationException("Enumerator is at its initial position thus cannot return any value."); 39 | } 40 | } 41 | } 42 | 43 | object IEnumerator.Current => this.Current; 44 | 45 | public bool MoveNext() 46 | { 47 | this.position = this.position >= this.maxPosition 48 | ? FirstElementPosition 49 | : this.position + 1; 50 | 51 | return true; 52 | } 53 | 54 | public void Reset() 55 | { 56 | this.position = InitialPosition; 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.Core/SpecimenBuilders/RandomFixedValuesGenerator.cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.Core.SpecimenBuilders 2 | { 3 | using System; 4 | using System.Collections; 5 | using System.Collections.Concurrent; 6 | using System.Diagnostics.CodeAnalysis; 7 | using System.Linq; 8 | 9 | using global::AutoFixture.Kernel; 10 | 11 | using Objectivity.AutoFixture.XUnit2.Core.Common; 12 | using Objectivity.AutoFixture.XUnit2.Core.Requests; 13 | 14 | internal sealed class RandomFixedValuesGenerator : ISpecimenBuilder 15 | { 16 | private readonly ConcurrentDictionary enumerators = new(); 17 | 18 | public object Create(object request, ISpecimenContext context) 19 | { 20 | if (context is null) 21 | { 22 | throw new ArgumentNullException(nameof(context)); 23 | } 24 | 25 | if (request.NotNull(nameof(request)) is FixedValuesRequest fixedValuesRequest) 26 | { 27 | return this.CreateValue(fixedValuesRequest); 28 | } 29 | 30 | return new NoSpecimen(); 31 | } 32 | 33 | [SuppressMessage("Security", "CA5394:Do not use insecure randomness", Justification = "It is good enough for collection randomization.")] 34 | private static IEnumerator CreateEnumerable(FixedValuesRequest request) 35 | { 36 | var random = new Random(); 37 | 38 | // Stryker disable once all : mutating ordering by random still brings random results 39 | var values = request.Values.OrderBy((_) => random.Next()).ToArray(); 40 | 41 | return new RoundRobinEnumerable(values); 42 | } 43 | 44 | private object CreateValue(FixedValuesRequest request) 45 | { 46 | var generator = this.enumerators.GetOrAdd(request, CreateEnumerable); 47 | generator.MoveNext(); 48 | 49 | return generator.Current; 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.Core.Tests/.editorconfig: -------------------------------------------------------------------------------- 1 | root = false 2 | 3 | [*.cs] 4 | 5 | # CA1062: Validate arguments of public methods 6 | dotnet_diagnostic.CA1062.severity = none 7 | # CA1506: Avoid excessive class coupling 8 | dotnet_diagnostic.CA1506.severity = none 9 | # CA1515: Consider making public types internal 10 | dotnet_diagnostic.CA1515.severity = none 11 | # CA1707: Identifiers should not contain underscores 12 | dotnet_diagnostic.CA1707.severity = none 13 | # CA1822: Mark members as static 14 | dotnet_diagnostic.CA1822.severity = none 15 | # CA1859: Use concrete types when possible for improved performance 16 | dotnet_diagnostic.CA1859.severity = none 17 | # CA1861: Avoid constant arrays as arguments 18 | dotnet_diagnostic.CA1861.severity = none 19 | # CA2000: Dispose objects before losing scope 20 | dotnet_diagnostic.CA2000.severity = none 21 | # CA2007: Consider calling ConfigureAwait on the awaited task 22 | dotnet_diagnostic.CA2007.severity = none 23 | # RCS1090: Call 'ConfigureAwait(false)'. 24 | dotnet_diagnostic.RCS1090.severity = none 25 | # S3376: Attribute, EventArgs, and Exception type names should end with the type being extended. 26 | dotnet_diagnostic.S3376.severity = none 27 | # S4158: Empty collections should not be accessed or iterated. 28 | dotnet_diagnostic.S4158.severity = none 29 | # S6608: Prefer indexing instead of "Enumerable" methods on types implementing "IList" 30 | dotnet_diagnostic.S6608.severity = none 31 | 32 | ## ReSharper 33 | 34 | # Possible 'System.NullReferenceException' 35 | resharper_possible_null_reference_exception_highlighting = none 36 | # Expression is always null 37 | resharper_expression_is_always_null_highlighting = none 38 | # Use collection expression syntax 39 | resharper_use_collection_expression_highlighting = none 40 | # Type member is never used (non-private accessibility) 41 | resharper_unused_member_global_highlighting = none 42 | # Member can be made private (non-private accessibility) 43 | resharper_member_can_be_private_global_highlighting = none 44 | # Redundant type declaration body 45 | resharper_redundant_type_declaration_body_highlighting = none -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.Core/Attributes/ExceptAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.Core.Attributes 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Reflection; 7 | 8 | using global::AutoFixture; 9 | using global::AutoFixture.Kernel; 10 | using global::AutoFixture.Xunit2; 11 | 12 | using Objectivity.AutoFixture.XUnit2.Core.Common; 13 | using Objectivity.AutoFixture.XUnit2.Core.Requests; 14 | using Objectivity.AutoFixture.XUnit2.Core.SpecimenBuilders; 15 | 16 | [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false)] 17 | public sealed class ExceptAttribute : CustomizeAttribute 18 | { 19 | private readonly HashSet inputValues; 20 | private readonly Lazy> readonlyValues; 21 | 22 | public ExceptAttribute(params object[] values) 23 | { 24 | this.inputValues = new HashSet(values.NotNull(nameof(values))); 25 | if (this.inputValues.Count == 0) 26 | { 27 | throw new ArgumentException("At least one value is expected to be specified.", nameof(values)); 28 | } 29 | 30 | this.readonlyValues = new Lazy>(() => Array.AsReadOnly(this.inputValues.ToArray())); 31 | } 32 | 33 | public IReadOnlyCollection Values => this.readonlyValues.Value; 34 | 35 | public override ICustomization GetCustomization(ParameterInfo parameter) 36 | { 37 | if (parameter is null) 38 | { 39 | throw new ArgumentNullException(nameof(parameter)); 40 | } 41 | 42 | return new CompositeSpecimenBuilder( 43 | new FilteringSpecimenBuilder( 44 | new RequestFactoryRelay((type) => new ExceptValuesRequest(type, this.inputValues.ToArray())), 45 | new EqualRequestSpecification(parameter)), 46 | new RandomExceptValuesGenerator()) 47 | .ToCustomization(); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.Core/Attributes/PickFromValuesAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.Core.Attributes 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Reflection; 7 | 8 | using global::AutoFixture; 9 | using global::AutoFixture.Kernel; 10 | using global::AutoFixture.Xunit2; 11 | 12 | using Objectivity.AutoFixture.XUnit2.Core.Common; 13 | using Objectivity.AutoFixture.XUnit2.Core.Requests; 14 | using Objectivity.AutoFixture.XUnit2.Core.SpecimenBuilders; 15 | 16 | [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false)] 17 | public sealed class PickFromValuesAttribute : CustomizeAttribute 18 | { 19 | private readonly HashSet inputValues; 20 | private readonly Lazy> readonlyValues; 21 | 22 | public PickFromValuesAttribute(params object[] values) 23 | { 24 | this.inputValues = new HashSet(values.NotNull(nameof(values))); 25 | if (this.inputValues.Count == 0) 26 | { 27 | throw new ArgumentException("At least one value is expected to be specified.", nameof(values)); 28 | } 29 | 30 | this.readonlyValues = new Lazy>(() => Array.AsReadOnly(this.inputValues.ToArray())); 31 | } 32 | 33 | public IReadOnlyCollection Values => this.readonlyValues.Value; 34 | 35 | public override ICustomization GetCustomization(ParameterInfo parameter) 36 | { 37 | if (parameter is null) 38 | { 39 | throw new ArgumentNullException(nameof(parameter)); 40 | } 41 | 42 | return new CompositeSpecimenBuilder( 43 | new FilteringSpecimenBuilder( 44 | new RequestFactoryRelay((type) => new FixedValuesRequest(type, this.inputValues.ToArray())), 45 | new EqualRequestSpecification(parameter)), 46 | new RandomFixedValuesGenerator()) 47 | .ToCustomization(); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.Core.Tests/Customizations/AutoDataCommonCustomizationTests.cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.Core.Tests.Customizations 2 | { 3 | using global::AutoFixture; 4 | using global::AutoFixture.Xunit2; 5 | using Objectivity.AutoFixture.XUnit2.Core.Customizations; 6 | 7 | using Xunit; 8 | 9 | [Collection("AutoDataCommonCustomization")] 10 | [Trait("Category", "Customizations")] 11 | public class AutoDataCommonCustomizationTests 12 | { 13 | [AutoData] 14 | [Theory(DisplayName = "GIVEN existing customization with ignoring virtual members WHEN Customize is invoked THEN fixture is appropriately customized")] 15 | public void GivenExistingCustomizationForFixture_WhenCustomizeIsInvoked_ThenFixtureIsAppropriatelyCustomized(Fixture fixture) 16 | { 17 | // Arrange 18 | const bool ignoreVirtualMembers = true; 19 | var customization = new AutoDataCommonCustomization(ignoreVirtualMembers); 20 | 21 | // Act 22 | fixture.Customize(customization); 23 | 24 | // Assert 25 | fixture.ShouldNotThrowOnRecursion(); 26 | fixture.ShouldOmitRecursion(); 27 | fixture.ShouldIgnoreVirtualMembers(); 28 | } 29 | 30 | [AutoData] 31 | [Theory(DisplayName = "GIVEN existing customization without ignoring virtual members WHEN Customize is invoked THEN fixture is appropriately customized")] 32 | public void GivenExistingCustomizationWithoutIgnoringVirtualMembers_WhenCustomizeIsInvoked_ThenFixtureIsAppropriatelyCustomized(Fixture fixture) 33 | { 34 | // Arrange 35 | const bool ignoreVirtualMembers = false; 36 | var customization = new AutoDataCommonCustomization(ignoreVirtualMembers); 37 | 38 | // Act 39 | fixture.Customize(customization); 40 | 41 | // Assert 42 | fixture.ShouldNotThrowOnRecursion(); 43 | fixture.ShouldOmitRecursion(); 44 | fixture.ShouldNotIgnoreVirtualMembers(); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /.github/actions/test-and-collect-coverage/action.yml: -------------------------------------------------------------------------------- 1 | name: Test module & collect code coverage 2 | description: Run tests against specified module collecting code coverage 3 | inputs: 4 | codecov-token: 5 | description: Value of Codecov token used to upload code coverage results 6 | required: true 7 | coverage-directory: 8 | description: Path to code coverage directory where results are being stored 9 | required: false 10 | default: ${{ github.workspace }}\src\opencover 11 | module-name: 12 | description: Name of the module 13 | required: true 14 | module-namespace: 15 | description: Name of the module namespace 16 | required: true 17 | target-framework: 18 | description: Framework version to run tests against 19 | required: true 20 | runs: 21 | using: composite 22 | steps: 23 | - name: 🧪 test ${{ inputs.module-name }} in ${{ inputs.target-framework }} & collect coverage 24 | id: test-and-collect-code-coverage 25 | shell: pwsh 26 | run: | 27 | $ErrorActionPreference = 'stop' 28 | $path = [IO.Path]::Combine("${env:COVERAGE_DIRECTORY}", "${env:MODULE_NAMESPACE}.${env:MODULE_NAME}.xml") 29 | dotnet test ./src/${env:MODULE_NAMESPACE}.${env:MODULE_NAME}.Tests/ --no-build -f ${env:TARGET_FRAMEWORK} -e:CollectCoverage=true -e:CoverletOutputFormat=opencover -e:Exclude="[xunit*]*" -e:CoverletOutput=$path 30 | if ($LastExitCode -ne 0) { 31 | throw "dotnet test failed with exit code $LastExitCode" 32 | } 33 | 34 | "FILE=${env:MODULE_NAMESPACE}.${env:MODULE_NAME}.${env:TARGET_FRAMEWORK}.xml" >> $env:GITHUB_OUTPUT 35 | env: 36 | COVERAGE_DIRECTORY: ${{ inputs.coverage-directory }} 37 | MODULE_NAME: ${{ inputs.module-name }} 38 | MODULE_NAMESPACE: ${{ inputs.module-namespace }} 39 | TARGET_FRAMEWORK: ${{ inputs.target-framework }} 40 | - name: 📤 upload coverage reports to Codecov 41 | uses: codecov/codecov-action@v3 42 | with: 43 | token: ${{ inputs.codecov-token }} 44 | files: ${{ steps.test-and-collect-code-coverage.outputs.FILE }} 45 | directory: ${{ inputs.coverage-directory }} 46 | flags: unittests 47 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.Core.Tests/FixtureAssertionExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.Core.Tests 2 | { 3 | using System; 4 | using System.Linq; 5 | 6 | using global::AutoFixture; 7 | using global::AutoFixture.Kernel; 8 | 9 | using Objectivity.AutoFixture.XUnit2.Core.SpecimenBuilders; 10 | 11 | using Xunit; 12 | 13 | internal static class FixtureAssertionExtensions 14 | { 15 | internal static void ShouldNotThrowOnRecursion(this IFixture fixture) 16 | { 17 | // Ensure there is no behavior for throwing exception on recursive structures. 18 | Assert.DoesNotContain(fixture.Behaviors, IsSpecimenBuilderTransformation); 19 | } 20 | 21 | internal static void ShouldOmitRecursion(this IFixture fixture) 22 | { 23 | // Ensure there is a behavior added for omitting recursive types 24 | // on default recursion depth. 25 | Assert.Single(fixture.Behaviors, IsSpecimenBuilderTransformation); 26 | } 27 | 28 | internal static void ShouldNotIgnoreVirtualMembers(this IFixture fixture) 29 | { 30 | Assert.DoesNotContain(fixture.Customizations, IsSpecimenBuilder); 31 | } 32 | 33 | internal static void ShouldIgnoreVirtualMembers(this IFixture fixture) 34 | { 35 | Assert.Single(fixture.Customizations, IsSpecimenBuilder); 36 | } 37 | 38 | internal static void ShouldIgnoreVirtualMembers(this IFixture fixture, Type reflectedType) 39 | { 40 | bool IsReflectedOnType(IgnoreVirtualMembersSpecimenBuilder c) => c.ReflectedType == reflectedType; 41 | Assert.Single(fixture.Customizations.OfType(), IsReflectedOnType); 42 | } 43 | 44 | private static bool IsSpecimenBuilderTransformation(ISpecimenBuilderTransformation b) 45 | where T : ISpecimenBuilderTransformation => b is T; 46 | 47 | private static bool IsSpecimenBuilder(ISpecimenBuilder s) 48 | where T : ISpecimenBuilder => s is T; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.Core/Common/EnumerableExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.Core.Common 2 | { 3 | using System; 4 | using System.Collections; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Reflection; 8 | 9 | using JetBrains.Annotations; 10 | 11 | internal static class EnumerableExtensions 12 | { 13 | private static readonly MethodInfo BuildTypedArrayMethodInfo = 14 | typeof(EnumerableExtensions).GetTypeInfo().GetMethod( 15 | nameof(BuildTypedArray), 16 | BindingFlags.Static | BindingFlags.NonPublic); 17 | 18 | public static bool TryGetEnumerableSingleTypeArgument(this Type type, out Type argument) 19 | { 20 | if (type.NotNull(nameof(type)).IsArray) 21 | { 22 | argument = type.GetElementType(); 23 | return true; 24 | } 25 | 26 | var interfaces = type.GetInterfaces(); 27 | if (type.IsInterface) 28 | { 29 | interfaces = interfaces.Append(type).ToArray(); 30 | } 31 | 32 | var genericInterface = Array.Find( 33 | interfaces, 34 | x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IEnumerable<>)); 35 | if (genericInterface is not null) 36 | { 37 | var typeArguments = genericInterface.GenericTypeArguments; 38 | if (typeArguments.Length == 1) 39 | { 40 | argument = typeArguments[0]; 41 | return true; 42 | } 43 | } 44 | 45 | argument = null; 46 | return false; 47 | } 48 | 49 | public static object ToTypedArray([NoEnumeration] this IEnumerable items, Type itemType) 50 | { 51 | var method = BuildTypedArrayMethodInfo.MakeGenericMethod(itemType.NotNull(nameof(itemType))); 52 | return method.Invoke(null, new object[] { items.NotNull(nameof(items)) }); 53 | } 54 | 55 | private static TElementType[] BuildTypedArray(IEnumerable items) 56 | { 57 | return items.Cast() 58 | .ToArray(); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /.github/workflows/test-mutations.yml: -------------------------------------------------------------------------------- 1 | name: '👾 Stryker.NET: Mutation testing' 2 | 3 | on: 4 | pull_request: 5 | paths: 6 | - 'stryker-config.yml' 7 | - 'src/**' 8 | - '!src/qodana.yml' 9 | - '.github/workflows/test-mutations.yml' 10 | - '.github/actions/materialize-signing-key/**' 11 | types: [opened, synchronize, reopened] 12 | push: 13 | branches: 14 | - 'master' 15 | paths: 16 | - 'stryker-config.yml' 17 | - 'src/**' 18 | - '!src/qodana.yml' 19 | - '.github/workflows/test-mutations.yml' 20 | - '.github/actions/materialize-signing-key/**' 21 | workflow_dispatch: 22 | 23 | env: 24 | DOTNET_NOLOGO: true 25 | DOTNET_CLI_TELEMETRY_OPTOUT: true 26 | Configuration: Release 27 | 28 | defaults: 29 | run: 30 | shell: pwsh 31 | 32 | concurrency: 33 | group: ${{ github.workflow }}-${{ github.ref }} 34 | cancel-in-progress: true 35 | 36 | jobs: 37 | test: 38 | runs-on: ubuntu-latest 39 | steps: 40 | - name: 📥 checkout 41 | uses: actions/checkout@v6 42 | with: 43 | fetch-depth: 0 44 | - name: 🖊️ materialize signing key 45 | id: signing-key 46 | uses: ./.github/actions/materialize-signing-key 47 | with: 48 | signing-key-value: ${{ secrets.SIGNING_KEY }} 49 | - name: 💾 install stryker.net 50 | run: | 51 | $ErrorActionPreference = 'stop' 52 | dotnet new tool-manifest 53 | if ($LastExitCode -ne 0) { 54 | throw "dotnet new failed with exit code $LastExitCode" 55 | } 56 | 57 | dotnet tool install --local dotnet-stryker 58 | if ($LastExitCode -ne 0) { 59 | throw "dotnet tool install failed with exit code $LastExitCode" 60 | } 61 | - name: 👾 test mutations 62 | working-directory: ./src 63 | run: | 64 | $ErrorActionPreference = 'stop' 65 | dotnet tool run dotnet-stryker -f ../stryker-config.yml -r dashboard -v ${env:BRANCH_NAME} --dashboard-api-key ${env:API_KEY} 66 | if ($LastExitCode -ne 0) { 67 | throw "dotnet tool run failed with exit code $LastExitCode" 68 | } 69 | env: 70 | API_KEY: ${{ secrets.STRYKER_API_KEY }} 71 | BRANCH_NAME: ${{ github.ref_name }} 72 | StrongNameKey: ${{ secrets.SIGNING_KEY }} 73 | StrongNameKeyPath: ${{ steps.signing-key.outputs.file-path }} 74 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.Core/Attributes/CustomizeWithAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.Core.Attributes 2 | { 3 | using System; 4 | using System.Diagnostics.CodeAnalysis; 5 | using System.Linq; 6 | using System.Reflection; 7 | 8 | using global::AutoFixture; 9 | using global::AutoFixture.Xunit2; 10 | 11 | using Objectivity.AutoFixture.XUnit2.Core.Common; 12 | 13 | [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false)] 14 | [SuppressMessage("Performance", "CA1813:Avoid unsealed attributes", Justification = "This attribute should be extendable by inheritance.")] 15 | public class CustomizeWithAttribute : CustomizeAttribute 16 | { 17 | public CustomizeWithAttribute(Type type, params object[] args) 18 | { 19 | this.Type = type.NotNull(nameof(type)); 20 | 21 | var customizationType = typeof(ICustomization); 22 | if (!customizationType.IsAssignableFrom(type)) 23 | { 24 | throw new ArgumentException($"Specified argument {nameof(type)} must implement {customizationType.Name}"); 25 | } 26 | 27 | this.Args = args; 28 | } 29 | 30 | [SuppressMessage("ReSharper", "MemberCanBePrivate.Global", Justification = "Testable design.")] 31 | public Type Type { get; } 32 | 33 | [SuppressMessage("ReSharper", "MemberCanBePrivate.Global", Justification = "Testable design.")] 34 | public object[] Args { get; } 35 | 36 | /// 37 | /// Gets or sets a value indicating whether attribute target parameter type should included as a first argument when creating customization. 38 | /// 39 | /// Indicates whether attribute target parameter type should included as a first argument when creating customization. 40 | public bool IncludeParameterType { get; set; } 41 | 42 | public override ICustomization GetCustomization(ParameterInfo parameter) 43 | { 44 | var args = this.IncludeParameterType 45 | ? new object[] { parameter.NotNull(nameof(parameter)).ParameterType } 46 | .Concat(this.Args ?? Array.Empty()) 47 | .ToArray() 48 | : this.Args; 49 | 50 | return Activator.CreateInstance(this.Type, args) as ICustomization; 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.Core/Attributes/InlineAutoDataBaseAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.Core.Attributes 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Diagnostics.CodeAnalysis; 6 | using System.Reflection; 7 | 8 | using global::AutoFixture; 9 | 10 | using Objectivity.AutoFixture.XUnit2.Core.Common; 11 | using Objectivity.AutoFixture.XUnit2.Core.Customizations; 12 | using Objectivity.AutoFixture.XUnit2.Core.Providers; 13 | 14 | using Xunit.Sdk; 15 | 16 | [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] 17 | public abstract class InlineAutoDataBaseAttribute : DataAttribute 18 | { 19 | private readonly object[] inputValues; 20 | private readonly Lazy> readonlyValues; 21 | 22 | protected InlineAutoDataBaseAttribute(IFixture fixture, IAutoFixtureInlineAttributeProvider provider, params object[] values) 23 | { 24 | this.Provider = provider.NotNull(nameof(provider)); 25 | this.Fixture = fixture.NotNull(nameof(fixture)); 26 | this.inputValues = values ?? Array.Empty(); 27 | this.readonlyValues = new Lazy>(() => Array.AsReadOnly(this.inputValues)); 28 | } 29 | 30 | public IFixture Fixture { get; } 31 | 32 | public IAutoFixtureInlineAttributeProvider Provider { get; } 33 | 34 | /// 35 | /// Gets or sets a value indicating whether virtual members should be ignored during object creation. 36 | /// 37 | /// Indicates whether virtual members should be ignored during object creation. 38 | public bool IgnoreVirtualMembers { get; set; } 39 | 40 | public IReadOnlyCollection Values => this.readonlyValues.Value; 41 | 42 | public override IEnumerable GetData(MethodInfo testMethod) 43 | { 44 | this.Fixture.Customize(new AutoDataCommonCustomization(this.IgnoreVirtualMembers)); 45 | this.Customize(this.Fixture); 46 | 47 | return this.Provider.GetAttribute(this.Fixture, this.inputValues).GetData(testMethod); 48 | } 49 | 50 | [SuppressMessage("ReSharper", "UnusedMethodReturnValue.Global", Justification = "Align design with AutoFixture.")] 51 | protected abstract IFixture Customize(IFixture fixture); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.Core/Attributes/PickFromRangeAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.Core.Attributes 2 | { 3 | using System; 4 | using System.Reflection; 5 | 6 | using global::AutoFixture; 7 | using global::AutoFixture.Kernel; 8 | using global::AutoFixture.Xunit2; 9 | 10 | using Objectivity.AutoFixture.XUnit2.Core.SpecimenBuilders; 11 | 12 | [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false)] 13 | public sealed class PickFromRangeAttribute : CustomizeAttribute 14 | { 15 | public PickFromRangeAttribute(int minimum, int maximum) 16 | : this((object)minimum, maximum) 17 | { 18 | } 19 | 20 | public PickFromRangeAttribute(uint minimum, uint maximum) 21 | : this((object)minimum, maximum) 22 | { 23 | } 24 | 25 | public PickFromRangeAttribute(long minimum, long maximum) 26 | : this((object)minimum, maximum) 27 | { 28 | } 29 | 30 | public PickFromRangeAttribute(ulong minimum, ulong maximum) 31 | : this((object)minimum, maximum) 32 | { 33 | } 34 | 35 | public PickFromRangeAttribute(double minimum, double maximum) 36 | : this((object)minimum, maximum) 37 | { 38 | } 39 | 40 | public PickFromRangeAttribute(float minimum, float maximum) 41 | : this((object)minimum, maximum) 42 | { 43 | } 44 | 45 | private PickFromRangeAttribute(object minimum, object maximum) 46 | { 47 | if (((IComparable)minimum).CompareTo((IComparable)maximum) > 0) 48 | { 49 | throw new ArgumentOutOfRangeException(nameof(minimum), $"Parameter {nameof(minimum)} must be lower or equal to parameter {nameof(maximum)}."); 50 | } 51 | 52 | this.Minimum = minimum; 53 | this.Maximum = maximum; 54 | } 55 | 56 | public object Minimum { get; } 57 | 58 | public object Maximum { get; } 59 | 60 | public override ICustomization GetCustomization(ParameterInfo parameter) 61 | { 62 | if (parameter is null) 63 | { 64 | throw new ArgumentNullException(nameof(parameter)); 65 | } 66 | 67 | return new FilteringSpecimenBuilder( 68 | new RequestFactoryRelay((type) => new RangedNumberRequest(type, this.Minimum, this.Maximum)), 69 | new EqualRequestSpecification(parameter)) 70 | .ToCustomization(); 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.Core/Attributes/AutoDataAdapterAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.Core.Attributes 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Reflection; 7 | 8 | using global::AutoFixture; 9 | using global::AutoFixture.Kernel; 10 | using global::AutoFixture.Xunit2; 11 | using Objectivity.AutoFixture.XUnit2.Core.Common; 12 | using Objectivity.AutoFixture.XUnit2.Core.Comparers; 13 | 14 | [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)] 15 | internal sealed class AutoDataAdapterAttribute : AutoDataAttribute 16 | { 17 | public AutoDataAdapterAttribute(IFixture fixture, params object[] inlineValues) 18 | : base(() => fixture) 19 | { 20 | this.AdaptedFixture = fixture.NotNull(nameof(fixture)); 21 | this.InlineValues = Array.AsReadOnly(inlineValues ?? Array.Empty()); 22 | } 23 | 24 | public IFixture AdaptedFixture { get; } 25 | 26 | public IReadOnlyCollection InlineValues { get; } 27 | 28 | public override IEnumerable GetData(MethodInfo testMethod) 29 | { 30 | // This is an extension of AutoDataAttribute.GetData method 31 | // with the ability to skip already provided inline values 32 | var parameters = testMethod.NotNull(nameof(testMethod)).GetParameters(); 33 | var specimens = new List(this.InlineValues); 34 | foreach (var p in parameters.Skip(this.InlineValues.Count)) 35 | { 36 | this.CustomizeFixture(p); 37 | 38 | var specimen = this.Resolve(p); 39 | specimens.Add(specimen); 40 | } 41 | 42 | return new[] { specimens.ToArray() }; 43 | } 44 | 45 | private void CustomizeFixture(ParameterInfo p) 46 | { 47 | var customizeAttributes = p.GetCustomAttributes() 48 | .OfType() 49 | .OrderBy(x => x, new CustomizeAttributeComparer()); 50 | 51 | foreach (var ca in customizeAttributes) 52 | { 53 | var c = ca.GetCustomization(p); 54 | this.AdaptedFixture.Customize(c); 55 | } 56 | } 57 | 58 | private object Resolve(ParameterInfo p) 59 | { 60 | var context = new SpecimenContext(this.AdaptedFixture); 61 | return context.Resolve(p); 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.Core/SpecimenBuilders/RequestFactoryRelay.cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.Core.SpecimenBuilders 2 | { 3 | using System; 4 | using System.Collections; 5 | using System.Reflection; 6 | 7 | using global::AutoFixture.Kernel; 8 | 9 | using Objectivity.AutoFixture.XUnit2.Core.Common; 10 | 11 | internal sealed class RequestFactoryRelay : ISpecimenBuilder 12 | { 13 | private readonly Func requestFactory; 14 | 15 | public RequestFactoryRelay(Func requestFactory) 16 | { 17 | this.requestFactory = requestFactory.NotNull(nameof(requestFactory)); 18 | } 19 | 20 | public object Create(object request, ISpecimenContext context) 21 | { 22 | if (context is null) 23 | { 24 | throw new ArgumentNullException(nameof(context)); 25 | } 26 | 27 | if (request.NotNull(nameof(request)) is ParameterInfo parameterInfo) 28 | { 29 | var parameterType = Nullable.GetUnderlyingType(parameterInfo.ParameterType) 30 | ?? parameterInfo.ParameterType; 31 | 32 | return parameterType != typeof(string) 33 | && parameterType.TryGetEnumerableSingleTypeArgument(out var itemType) 34 | ? this.CreateMultiple(parameterType, itemType, context) 35 | : this.CreateSingle(parameterType, context); 36 | } 37 | 38 | return new NoSpecimen(); 39 | } 40 | 41 | private object CreateSingle(Type type, ISpecimenContext context) 42 | { 43 | var transformedRequest = this.requestFactory(type); 44 | return transformedRequest is not null 45 | ? context.Resolve(transformedRequest) 46 | : new NoSpecimen(); 47 | } 48 | 49 | private object CreateMultiple(Type collectionType, Type itemType, ISpecimenContext context) 50 | { 51 | var transformedRequest = this.requestFactory(itemType); 52 | if (transformedRequest is not null 53 | && context.Resolve(new MultipleRequest(transformedRequest)) is IEnumerable elements) 54 | { 55 | var items = elements.ToTypedArray(itemType); 56 | return collectionType.IsArray || collectionType.IsAbstract 57 | ? items 58 | : Activator.CreateInstance(collectionType, items); 59 | } 60 | 61 | return new NoSpecimen(); 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /.github/workflows/snyk.yml: -------------------------------------------------------------------------------- 1 | name: '🐕‍🦺 Snyk: Vulnerability Analysis' 2 | 3 | on: 4 | pull_request: 5 | paths: 6 | - 'src/**' 7 | - '!src/qodana.yml' 8 | - '.github/workflows/snyk.yml' 9 | types: [opened, synchronize, reopened] 10 | push: 11 | branches: 12 | - 'master' 13 | paths: 14 | - 'src/**' 15 | - '!src/qodana.yml' 16 | - '.github/workflows/snyk.yml' 17 | schedule: 18 | - cron: '14 6 * * 0' # Random time 19 | workflow_dispatch: 20 | 21 | defaults: 22 | run: 23 | shell: pwsh 24 | 25 | concurrency: 26 | group: ${{ github.workflow }}-${{ github.ref }} 27 | cancel-in-progress: true 28 | 29 | jobs: 30 | scan: 31 | runs-on: ubuntu-latest 32 | permissions: 33 | actions: read 34 | contents: read 35 | security-events: write 36 | steps: 37 | - name: 📥 checkout 38 | uses: actions/checkout@v6 39 | with: 40 | fetch-depth: 0 41 | - name: 🏗️ restore dependencies 42 | run: | 43 | $ErrorActionPreference = 'stop' 44 | dotnet restore ./src/Objectivity.AutoFixture.XUnit2.AutoMock.sln 45 | if ($LastExitCode -ne 0) { 46 | throw "dotnet restore failed with exit code $LastExitCode" 47 | } 48 | - name: 🔬 snyk opensource scan 49 | uses: snyk/actions/dotnet@master 50 | continue-on-error: true 51 | env: 52 | SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} 53 | with: 54 | args: --sarif-file-output=snyk/opensource.sarif --all-projects --exclude=Objectivity.AutoFixture.XUnit2.AutoFakeItEasy.Tests,Objectivity.AutoFixture.XUnit2.AutoMoq.Tests,Objectivity.AutoFixture.XUnit2.AutoNSubstitute.Tests,Objectivity.AutoFixture.XUnit2.Core.Tests 55 | - name: 🔬 snyk code scan 56 | uses: snyk/actions/dotnet@master 57 | continue-on-error: true 58 | env: 59 | SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} 60 | with: 61 | args: --sarif-file-output=snyk/code.sarif 62 | command: code test 63 | - name: 📈 snyk monitor 64 | uses: snyk/actions/dotnet@master 65 | env: 66 | SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} 67 | with: 68 | args: --all-projects --exclude=Objectivity.AutoFixture.XUnit2.AutoFakeItEasy.Tests,Objectivity.AutoFixture.XUnit2.AutoMoq.Tests,Objectivity.AutoFixture.XUnit2.AutoNSubstitute.Tests,Objectivity.AutoFixture.XUnit2.Core.Tests 69 | command: monitor 70 | - name: 📊 upload sarif file for GitHub Advanced Security Dashboard 71 | uses: github/codeql-action/upload-sarif@v4 72 | with: 73 | sarif_file: snyk 74 | if: ${{ always() }} 75 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.Core/Requests/ValuesRequest.cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.Core.Requests 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Globalization; 6 | using System.Linq; 7 | 8 | using Objectivity.AutoFixture.XUnit2.Core.Common; 9 | 10 | internal abstract class ValuesRequest : IEquatable 11 | where T : ValuesRequest 12 | { 13 | private readonly HashSet inputValues; 14 | private readonly Lazy> readonlyValues; 15 | 16 | protected ValuesRequest(Type operandType, params object[] values) 17 | { 18 | this.OperandType = operandType.NotNull(nameof(operandType)); 19 | this.inputValues = new HashSet(values.NotNull(nameof(values))); 20 | if (this.inputValues.Count == 0) 21 | { 22 | throw new ArgumentException("At least one value is expected to be specified.", nameof(values)); 23 | } 24 | 25 | this.readonlyValues = new Lazy>(() => Array.AsReadOnly(this.inputValues.ToArray())); 26 | } 27 | 28 | public Type OperandType { get; } 29 | 30 | public IReadOnlyCollection Values => this.readonlyValues.Value; 31 | 32 | public override bool Equals(object obj) 33 | { 34 | if (obj is T other) 35 | { 36 | return this.Equals(other); 37 | } 38 | 39 | return false; 40 | } 41 | 42 | public bool Equals(T other) 43 | { 44 | if (other is null) 45 | { 46 | return false; 47 | } 48 | 49 | return this.OperandType == other.OperandType 50 | && this.inputValues.SetEquals(other.Values); 51 | } 52 | 53 | public override int GetHashCode() 54 | { 55 | var hc = this.OperandType.GetHashCode() ^ typeof(T).GetHashCode(); 56 | foreach (var inputValue in this.inputValues.Where(x => x is not null)) 57 | { 58 | hc ^= inputValue.GetHashCode(); 59 | } 60 | 61 | return hc; 62 | } 63 | 64 | public override string ToString() 65 | { 66 | var values = string.Join(", ", this.inputValues.Select(x => $"[{(x?.GetType() ?? typeof(object)).Name}] {x ?? "null"}")); 67 | return string.Format( 68 | CultureInfo.CurrentCulture, 69 | "{0} (OperandType: {1}, Values: {2}", 70 | this.GetType().Name, 71 | this.OperandType.FullName, 72 | values); 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.Core.Tests/Customizations/IgnoreVirtualMembersCustomizationTests.cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.Core.Tests.Customizations 2 | { 3 | using System; 4 | 5 | using global::AutoFixture; 6 | using global::AutoFixture.Xunit2; 7 | using Objectivity.AutoFixture.XUnit2.Core.Customizations; 8 | 9 | using Xunit; 10 | 11 | [Collection("IgnoreVirtualMembersCustomization")] 12 | [Trait("Category", "Customizations")] 13 | public class IgnoreVirtualMembersCustomizationTests 14 | { 15 | [AutoData] 16 | [Theory(DisplayName = "GIVEN existing customization to ignore virtual members for fixture WHEN Customize is invoked THEN fixture should not create virtual members")] 17 | public void GivenExistingCustomizationToIgnoreVirtualMembersForFixture_WhenCustomizeIsInvoked_ThenFixtureShouldNotCreateVirtualMembers( 18 | Fixture fixture, 19 | [Modest] IgnoreVirtualMembersCustomization customization) 20 | { 21 | // Arrange 22 | // Act 23 | fixture.Customize(customization); 24 | 25 | // Assert 26 | fixture.ShouldIgnoreVirtualMembers(); 27 | } 28 | 29 | [AutoData] 30 | [Theory(DisplayName = "GIVEN existing customization to ignore virtual members for fixture WHEN Customize is invoked THEN fixture should not create virtual members")] 31 | public void GivenExistingCustomizationToIgnoreVirtualMembersWithTypeForFixture_WhenCustomizeIsInvoked_ThenFixtureShouldNotCreateVirtualMembers( 32 | Fixture fixture, 33 | [Frozen] Type reflectedType, 34 | [Greedy] IgnoreVirtualMembersCustomization customization) 35 | { 36 | // Arrange 37 | // Act 38 | fixture.Customize(customization); 39 | 40 | // Assert 41 | fixture.ShouldIgnoreVirtualMembers(reflectedType); 42 | } 43 | 44 | [Fact(DisplayName = "GIVEN default constructor WHEN invoked THEN reflected type should be null")] 45 | public void GivenDefaultConstructor_WhenInvoked_ThenReflectedTypeShouldBeNull() 46 | { 47 | // Arrange 48 | // Act 49 | var customization = new IgnoreVirtualMembersCustomization(); 50 | 51 | // Assert 52 | Assert.Null(customization.ReflectedType); 53 | } 54 | 55 | [AutoData] 56 | [Theory(DisplayName = "GIVEN existing type WHEN constructor with parameter is invoked THEN that type should be reflected")] 57 | public void GivenExistingType_WhenConstructorWithParameterIsInvoked_ThenThatTypeShouldBeReflected(Type reflectedType) 58 | { 59 | // Arrange 60 | // Act 61 | var customization = new IgnoreVirtualMembersCustomization(reflectedType); 62 | 63 | // Assert 64 | Assert.Same(reflectedType, customization.ReflectedType); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /.github/workflows/qodana.yml: -------------------------------------------------------------------------------- 1 | name: '🧠 Qodana: Static Code Analysis' 2 | 3 | on: 4 | pull_request: 5 | paths: 6 | - 'src/**' 7 | - '.github/workflows/qodana.yml' 8 | types: [opened, synchronize, reopened] 9 | push: 10 | branches: 11 | - 'master' 12 | paths: 13 | - 'src/**' 14 | - '.github/workflows/qodana.yml' 15 | schedule: 16 | - cron: '17 5 * * 0' # Random time 17 | workflow_dispatch: 18 | inputs: 19 | upload-result-as-artifact: 20 | description: 'Upload Qodana result as artifact' 21 | required: false 22 | type: boolean 23 | default: false 24 | log-level: 25 | description: 'Log level for Qodana scan' 26 | required: false 27 | type: choice 28 | default: 'error' 29 | options: 30 | - 'debug' 31 | - 'error' 32 | - 'trace' 33 | 34 | concurrency: 35 | group: ${{ github.workflow }}-${{ github.ref }} 36 | cancel-in-progress: true 37 | 38 | jobs: 39 | scan: 40 | # Skip push event by dependabot to avoid permission issues. 41 | if: ${{ github.actor != 'dependabot[bot]' || github.event_name != 'push' }} 42 | runs-on: ubuntu-latest 43 | permissions: 44 | contents: write 45 | pull-requests: write 46 | checks: write 47 | security-events: write 48 | steps: 49 | - name: 📥 checkout 50 | uses: actions/checkout@v6 51 | with: 52 | fetch-depth: 0 53 | - name: 💾 cache nuget packages 54 | uses: actions/cache@v5 55 | with: 56 | path: ${{ runner.temp }}/qodana/caches 57 | key: ${{ runner.os }}-qodana-${{ github.ref }}-${{ hashFiles('**/*.csproj') }} 58 | restore-keys: | 59 | ${{ runner.os }}-qodana-${{ github.ref }} 60 | - name: 🔬 qodana scan 61 | uses: JetBrains/qodana-action@v2025.2 62 | with: 63 | pr-mode: false 64 | post-pr-comment: true 65 | results-dir: ${{ runner.temp }}/qodana/results 66 | use-annotations: true 67 | use-caches: true 68 | cache-dir: ${{ runner.temp }}/qodana/caches 69 | primary-cache-key: ${{ runner.os }}-qodana-${{ github.ref }}-${{ hashFiles('**/*.csproj') }} 70 | additional-cache-key: ${{ runner.os }}-qodana-${{ github.ref }} 71 | upload-result: ${{ github.event_name == 'workflow_dispatch' && inputs.upload-result-as-artifact == true }} 72 | github-token: ${{ github.token }} 73 | args: | 74 | --project-dir,src, 75 | --log-level,${{ github.event_name == 'workflow_dispatch' && inputs.log-level || 'error' }}, 76 | --save-report=false 77 | env: 78 | QODANA_TOKEN: ${{ secrets.QODANA_TOKEN }} 79 | QODANA_ENDPOINT: 'https://qodana.cloud' 80 | - name: 📊 upload sarif file for GitHub Advanced Security Dashboard 81 | uses: github/codeql-action/upload-sarif@v4 82 | with: 83 | sarif_file: ${{ runner.temp }}/qodana/results/qodana.sarif.json 84 | if: ${{ always() }} 85 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.AutoMoq.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.7.34202.233 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Objectivity.AutoFixture.XUnit2.AutoMoq", "Objectivity.AutoFixture.XUnit2.AutoMoq\Objectivity.AutoFixture.XUnit2.AutoMoq.csproj", "{B7ADCA12-249E-4A13-90A3-16AD9E3EDFD0}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Objectivity.AutoFixture.XUnit2.AutoMoq.Tests", "Objectivity.AutoFixture.XUnit2.AutoMoq.Tests\Objectivity.AutoFixture.XUnit2.AutoMoq.Tests.csproj", "{B1851B64-3E9C-4EA2-A9F3-343B8D1EDB3D}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Objectivity.AutoFixture.XUnit2.Core", "Objectivity.AutoFixture.XUnit2.Core\Objectivity.AutoFixture.XUnit2.Core.csproj", "{6717BC95-F2D2-4EAE-A680-D871D58A773B}" 11 | EndProject 12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Objectivity.AutoFixture.XUnit2.Core.Tests", "Objectivity.AutoFixture.XUnit2.Core.Tests\Objectivity.AutoFixture.XUnit2.Core.Tests.csproj", "{BE5BF6E2-2EDC-4223-A89B-AE1D4BE1FF4E}" 13 | EndProject 14 | Global 15 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 16 | Debug|Any CPU = Debug|Any CPU 17 | Release|Any CPU = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 20 | {B7ADCA12-249E-4A13-90A3-16AD9E3EDFD0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {B7ADCA12-249E-4A13-90A3-16AD9E3EDFD0}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {B7ADCA12-249E-4A13-90A3-16AD9E3EDFD0}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {B7ADCA12-249E-4A13-90A3-16AD9E3EDFD0}.Release|Any CPU.Build.0 = Release|Any CPU 24 | {B1851B64-3E9C-4EA2-A9F3-343B8D1EDB3D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 25 | {B1851B64-3E9C-4EA2-A9F3-343B8D1EDB3D}.Debug|Any CPU.Build.0 = Debug|Any CPU 26 | {B1851B64-3E9C-4EA2-A9F3-343B8D1EDB3D}.Release|Any CPU.ActiveCfg = Release|Any CPU 27 | {B1851B64-3E9C-4EA2-A9F3-343B8D1EDB3D}.Release|Any CPU.Build.0 = Release|Any CPU 28 | {6717BC95-F2D2-4EAE-A680-D871D58A773B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 29 | {6717BC95-F2D2-4EAE-A680-D871D58A773B}.Debug|Any CPU.Build.0 = Debug|Any CPU 30 | {6717BC95-F2D2-4EAE-A680-D871D58A773B}.Release|Any CPU.ActiveCfg = Release|Any CPU 31 | {6717BC95-F2D2-4EAE-A680-D871D58A773B}.Release|Any CPU.Build.0 = Release|Any CPU 32 | {BE5BF6E2-2EDC-4223-A89B-AE1D4BE1FF4E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 33 | {BE5BF6E2-2EDC-4223-A89B-AE1D4BE1FF4E}.Debug|Any CPU.Build.0 = Debug|Any CPU 34 | {BE5BF6E2-2EDC-4223-A89B-AE1D4BE1FF4E}.Release|Any CPU.ActiveCfg = Release|Any CPU 35 | {BE5BF6E2-2EDC-4223-A89B-AE1D4BE1FF4E}.Release|Any CPU.Build.0 = Release|Any CPU 36 | EndGlobalSection 37 | GlobalSection(SolutionProperties) = preSolution 38 | HideSolutionNode = FALSE 39 | EndGlobalSection 40 | GlobalSection(ExtensibilityGlobals) = postSolution 41 | SolutionGuid = {E3AAE9C8-382F-4228-B7B2-74601518A964} 42 | EndGlobalSection 43 | EndGlobal 44 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.Core/Factories/NegativeValuesRequestFactory.cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.Core.Factories 2 | { 3 | using System; 4 | using System.Globalization; 5 | using System.Linq; 6 | 7 | using global::AutoFixture; 8 | using global::AutoFixture.Kernel; 9 | 10 | using Objectivity.AutoFixture.XUnit2.Core.Common; 11 | using Objectivity.AutoFixture.XUnit2.Core.Requests; 12 | 13 | internal class NegativeValuesRequestFactory : IFactory 14 | { 15 | private static readonly decimal DecimalEpsilon = new(1, 0, 0, true, 28); 16 | 17 | private static ObjectCreationException ObjectCreationException => new("The value could not be created. Probably attribute is specified for a type that does not accept negative values."); 18 | 19 | public object Create(Type input) 20 | { 21 | return input.NotNull(nameof(input)).IsEnum 22 | ? GetRequestForEnum(input) 23 | : GetRequestForNumericType(input); 24 | } 25 | 26 | private static FixedValuesRequest GetRequestForEnum(Type type) 27 | { 28 | var values = Type.GetTypeCode(type) switch 29 | { 30 | TypeCode.SByte => GetEnumNegativeValues(type), 31 | TypeCode.Int16 => GetEnumNegativeValues(type), 32 | TypeCode.Int32 => GetEnumNegativeValues(type), 33 | TypeCode.Int64 => GetEnumNegativeValues(type), 34 | _ => Array.Empty(), 35 | }; 36 | 37 | if (values.Length == 0) 38 | { 39 | throw ObjectCreationException; 40 | } 41 | 42 | return new FixedValuesRequest(type, values); 43 | } 44 | 45 | private static object[] GetEnumNegativeValues(Type type) 46 | where T : struct, IComparable 47 | { 48 | var zero = Convert.ChangeType(0, typeof(T), CultureInfo.InvariantCulture); 49 | return Enum.GetValues(type) 50 | .Cast() 51 | .Where(x => x.CompareTo(zero) < 0) 52 | .Select(x => Enum.ToObject(type, x)) 53 | .ToArray(); 54 | } 55 | 56 | private static RangedNumberRequest GetRequestForNumericType(Type type) 57 | { 58 | var (minimum, maximum) = Type.GetTypeCode(type) switch 59 | { 60 | TypeCode.Decimal => ((object, object))(decimal.MinValue, DecimalEpsilon), 61 | TypeCode.Double => (double.MinValue, -double.Epsilon), 62 | TypeCode.Int16 => (short.MinValue, (short)-1), 63 | TypeCode.Int32 => (int.MinValue, -1), 64 | TypeCode.Int64 => (long.MinValue, -1L), 65 | TypeCode.SByte => (sbyte.MinValue, (sbyte)-1), 66 | TypeCode.Single => (float.MinValue, -float.Epsilon), 67 | _ => throw ObjectCreationException, 68 | }; 69 | 70 | return new RangedNumberRequest(type, minimum, maximum); 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.AutoFakeItEasy.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.7.34202.233 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Objectivity.AutoFixture.XUnit2.Core", "Objectivity.AutoFixture.XUnit2.Core\Objectivity.AutoFixture.XUnit2.Core.csproj", "{B889895A-FC17-470A-B28E-61AAA8DBC1A4}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Objectivity.AutoFixture.XUnit2.Core.Tests", "Objectivity.AutoFixture.XUnit2.Core.Tests\Objectivity.AutoFixture.XUnit2.Core.Tests.csproj", "{EA3F7877-5CC7-4A58-802E-CFA8C0C45034}" 9 | EndProject 10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Objectivity.AutoFixture.XUnit2.AutoFakeItEasy", "Objectivity.AutoFixture.XUnit2.AutoFakeItEasy\Objectivity.AutoFixture.XUnit2.AutoFakeItEasy.csproj", "{7894039E-8188-49DF-9A3B-5D89F38947B9}" 11 | EndProject 12 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Objectivity.AutoFixture.XUnit2.AutoFakeItEasy.Tests", "Objectivity.AutoFixture.XUnit2.AutoFakeItEasy.Tests\Objectivity.AutoFixture.XUnit2.AutoFakeItEasy.Tests.csproj", "{26D21E2E-B6A2-4503-AF1F-6EEE6F1D99C5}" 13 | EndProject 14 | Global 15 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 16 | Debug|Any CPU = Debug|Any CPU 17 | Release|Any CPU = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 20 | {B889895A-FC17-470A-B28E-61AAA8DBC1A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {B889895A-FC17-470A-B28E-61AAA8DBC1A4}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {B889895A-FC17-470A-B28E-61AAA8DBC1A4}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {B889895A-FC17-470A-B28E-61AAA8DBC1A4}.Release|Any CPU.Build.0 = Release|Any CPU 24 | {EA3F7877-5CC7-4A58-802E-CFA8C0C45034}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 25 | {EA3F7877-5CC7-4A58-802E-CFA8C0C45034}.Debug|Any CPU.Build.0 = Debug|Any CPU 26 | {EA3F7877-5CC7-4A58-802E-CFA8C0C45034}.Release|Any CPU.ActiveCfg = Release|Any CPU 27 | {EA3F7877-5CC7-4A58-802E-CFA8C0C45034}.Release|Any CPU.Build.0 = Release|Any CPU 28 | {7894039E-8188-49DF-9A3B-5D89F38947B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 29 | {7894039E-8188-49DF-9A3B-5D89F38947B9}.Debug|Any CPU.Build.0 = Debug|Any CPU 30 | {7894039E-8188-49DF-9A3B-5D89F38947B9}.Release|Any CPU.ActiveCfg = Release|Any CPU 31 | {7894039E-8188-49DF-9A3B-5D89F38947B9}.Release|Any CPU.Build.0 = Release|Any CPU 32 | {26D21E2E-B6A2-4503-AF1F-6EEE6F1D99C5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 33 | {26D21E2E-B6A2-4503-AF1F-6EEE6F1D99C5}.Debug|Any CPU.Build.0 = Debug|Any CPU 34 | {26D21E2E-B6A2-4503-AF1F-6EEE6F1D99C5}.Release|Any CPU.ActiveCfg = Release|Any CPU 35 | {26D21E2E-B6A2-4503-AF1F-6EEE6F1D99C5}.Release|Any CPU.Build.0 = Release|Any CPU 36 | EndGlobalSection 37 | GlobalSection(SolutionProperties) = preSolution 38 | HideSolutionNode = FALSE 39 | EndGlobalSection 40 | GlobalSection(ExtensibilityGlobals) = postSolution 41 | SolutionGuid = {CA0EFCF9-9B4B-4753-ACC1-513F75600997} 42 | EndGlobalSection 43 | EndGlobal 44 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.AutoNSubstitute.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.7.34202.233 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Objectivity.AutoFixture.XUnit2.AutoNSubstitute", "Objectivity.AutoFixture.XUnit2.AutoNSubstitute\Objectivity.AutoFixture.XUnit2.AutoNSubstitute.csproj", "{D3E477EA-F0A1-4287-A22D-C8D982231849}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Objectivity.AutoFixture.XUnit2.AutoNSubstitute.Tests", "Objectivity.AutoFixture.XUnit2.AutoNSubstitute.Tests\Objectivity.AutoFixture.XUnit2.AutoNSubstitute.Tests.csproj", "{05464055-95CA-4BD8-A1C4-9E01885351B3}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Objectivity.AutoFixture.XUnit2.Core", "Objectivity.AutoFixture.XUnit2.Core\Objectivity.AutoFixture.XUnit2.Core.csproj", "{6717BC95-F2D2-4EAE-A680-D871D58A773B}" 11 | EndProject 12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Objectivity.AutoFixture.XUnit2.Core.Tests", "Objectivity.AutoFixture.XUnit2.Core.Tests\Objectivity.AutoFixture.XUnit2.Core.Tests.csproj", "{BE5BF6E2-2EDC-4223-A89B-AE1D4BE1FF4E}" 13 | EndProject 14 | Global 15 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 16 | Debug|Any CPU = Debug|Any CPU 17 | Release|Any CPU = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 20 | {D3E477EA-F0A1-4287-A22D-C8D982231849}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {D3E477EA-F0A1-4287-A22D-C8D982231849}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {D3E477EA-F0A1-4287-A22D-C8D982231849}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {D3E477EA-F0A1-4287-A22D-C8D982231849}.Release|Any CPU.Build.0 = Release|Any CPU 24 | {05464055-95CA-4BD8-A1C4-9E01885351B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 25 | {05464055-95CA-4BD8-A1C4-9E01885351B3}.Debug|Any CPU.Build.0 = Debug|Any CPU 26 | {05464055-95CA-4BD8-A1C4-9E01885351B3}.Release|Any CPU.ActiveCfg = Release|Any CPU 27 | {05464055-95CA-4BD8-A1C4-9E01885351B3}.Release|Any CPU.Build.0 = Release|Any CPU 28 | {6717BC95-F2D2-4EAE-A680-D871D58A773B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 29 | {6717BC95-F2D2-4EAE-A680-D871D58A773B}.Debug|Any CPU.Build.0 = Debug|Any CPU 30 | {6717BC95-F2D2-4EAE-A680-D871D58A773B}.Release|Any CPU.ActiveCfg = Release|Any CPU 31 | {6717BC95-F2D2-4EAE-A680-D871D58A773B}.Release|Any CPU.Build.0 = Release|Any CPU 32 | {BE5BF6E2-2EDC-4223-A89B-AE1D4BE1FF4E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 33 | {BE5BF6E2-2EDC-4223-A89B-AE1D4BE1FF4E}.Debug|Any CPU.Build.0 = Debug|Any CPU 34 | {BE5BF6E2-2EDC-4223-A89B-AE1D4BE1FF4E}.Release|Any CPU.ActiveCfg = Release|Any CPU 35 | {BE5BF6E2-2EDC-4223-A89B-AE1D4BE1FF4E}.Release|Any CPU.Build.0 = Release|Any CPU 36 | EndGlobalSection 37 | GlobalSection(SolutionProperties) = preSolution 38 | HideSolutionNode = FALSE 39 | EndGlobalSection 40 | GlobalSection(ExtensibilityGlobals) = postSolution 41 | SolutionGuid = {BBE586AB-DA28-47E4-9E95-4D9A9C69456E} 42 | EndGlobalSection 43 | EndGlobal 44 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.Core.Tests/Attributes/AutoDataBaseAttributeTests.cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.Core.Tests.Attributes 2 | { 3 | using System; 4 | 5 | using global::AutoFixture; 6 | using global::AutoFixture.Xunit2; 7 | using Moq; 8 | 9 | using Objectivity.AutoFixture.XUnit2.Core.Attributes; 10 | using Objectivity.AutoFixture.XUnit2.Core.Providers; 11 | 12 | using Xunit; 13 | 14 | [Collection("AutoDataBaseAttribute")] 15 | [Trait("Category", "DataAttribute")] 16 | public class AutoDataBaseAttributeTests 17 | { 18 | [AutoData] 19 | [Theory(DisplayName = "GIVEN existing fixture and attribute provider WHEN constructor is invoked THEN has specified fixture and attribute provider")] 20 | public void GivenExistingFixtureAndAttributeProvider_WhenConstructorIsInvoked_ThenHasSpecifiedFixtureAndAttributeProvider(Fixture fixture) 21 | { 22 | // Arrange 23 | var provider = new Mock(); 24 | 25 | // Act 26 | var attribute = new AutoDataBaseAttributeUnderTest(fixture, provider.Object); 27 | 28 | // Assert 29 | Assert.Equal(fixture, attribute.Fixture); 30 | Assert.Equal(provider.Object, attribute.Provider); 31 | Assert.False(attribute.IgnoreVirtualMembers); 32 | } 33 | 34 | [Fact(DisplayName = "GIVEN uninitialized fixture WHEN constructor is invoked THEN exception is thrown")] 35 | public void GivenUninitializedFixture_WhenConstructorIsInvoked_ThenExceptionIsThrown() 36 | { 37 | // Arrange 38 | const Fixture fixture = null; 39 | var provider = new Mock(); 40 | 41 | // Act 42 | object Act() => new AutoDataBaseAttributeUnderTest(fixture, provider.Object); 43 | 44 | // Assert 45 | var exception = Assert.Throws(Act); 46 | Assert.Equal("fixture", exception.ParamName); 47 | } 48 | 49 | [AutoData] 50 | [Theory(DisplayName = "GIVEN uninitialized attribute provider WHEN constructor is invoked THEN exception is thrown")] 51 | public void GivenUninitializedAttributeProvider_WhenConstructorIsInvoked_ThenExceptionIsThrown(Fixture fixture) 52 | { 53 | // Arrange 54 | const IAutoFixtureAttributeProvider provider = null; 55 | 56 | // Act 57 | object Act() => new AutoDataBaseAttributeUnderTest(fixture, provider); 58 | 59 | // Assert 60 | var exception = Assert.Throws(Act); 61 | Assert.Equal("provider", exception.ParamName); 62 | } 63 | 64 | [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)] 65 | private sealed class AutoDataBaseAttributeUnderTest : AutoDataBaseAttribute 66 | { 67 | public AutoDataBaseAttributeUnderTest(IFixture fixture, IAutoFixtureAttributeProvider provider) 68 | : base(fixture, provider) 69 | { 70 | } 71 | 72 | protected override IFixture Customize(IFixture fixture) 73 | { 74 | throw new NotImplementedException(); 75 | } 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /.github/workflows/init.yml: -------------------------------------------------------------------------------- 1 | name: '🎱 Prepare workflows configuration' 2 | 3 | on: 4 | workflow_call: 5 | inputs: 6 | buildAutoFakeItEasy: 7 | description: 'Build AutoFakeItEasy' 8 | required: false 9 | type: boolean 10 | default: true 11 | buildAutoMoq: 12 | description: 'Build AutoMoq' 13 | required: false 14 | type: boolean 15 | default: true 16 | buildAutoNSubstitute: 17 | description: 'Build AutoNSubstitute' 18 | required: false 19 | type: boolean 20 | default: true 21 | outputs: 22 | modules: 23 | description: Modules to build and pack 24 | value: ${{ jobs.run.outputs.modules }} 25 | version: 26 | description: Version used for building, packing and tagging 27 | value: ${{ jobs.run.outputs.version }} 28 | namespace: 29 | description: Global namespace 30 | value: Objectivity.AutoFixture.XUnit2 31 | configuration: 32 | description: Global build configuration 33 | value: Release 34 | 35 | defaults: 36 | run: 37 | shell: pwsh 38 | 39 | jobs: 40 | run: 41 | runs-on: ubuntu-latest 42 | timeout-minutes: 15 43 | permissions: 44 | contents: read 45 | outputs: 46 | modules: ${{ steps.determine-modules.outputs.modules }} 47 | version: ${{ steps.determine-version.outputs.version }} 48 | steps: 49 | - name: 📥 checkout 50 | uses: actions/checkout@v6 51 | with: 52 | fetch-depth: 0 53 | - name: 🎰 determine modules 54 | id: determine-modules 55 | run: | 56 | $ErrorActionPreference = 'stop' 57 | $inputModules = @{ 58 | AutoMoq = "${env:BUILD_AUTO_MOQ}"; 59 | AutoNSubstitute = "${env:BUILD_AUTO_NSUBSTITUTE}"; 60 | AutoFakeItEasy = "${env:BUILD_AUTO_FAKEITEASY}" 61 | } 62 | 63 | Write-Output "::group::Input parameters" 64 | foreach ($module in $inputModules.GetEnumerator()) { 65 | Write-Output "Build $($module.Name): $($module.Value)" 66 | } 67 | Write-Output "::endgroup::" 68 | 69 | $selectedModules = @() 70 | foreach ($module in $inputModules.GetEnumerator()) { 71 | [bool]$shouldBuildModule = $true 72 | if ([bool]::TryParse($module.Value, [ref]$shouldBuildModule) -eq $false) { 73 | Write-Host "::debug::Unable to parse input value for module $($module.Name)." 74 | } 75 | if ($shouldBuildModule) { 76 | $selectedModules += $module.Name 77 | } 78 | } 79 | 80 | if ($selectedModules.count -gt 0) { $selectedModules = @("Core") + $selectedModules } 81 | Write-Output "::group::Selected modules" 82 | foreach ($selectedModule in $selectedModules) { 83 | Write-Output "$($selectedModule)" 84 | } 85 | Write-Output "::endgroup::" 86 | 87 | "modules=$($selectedModules | ConvertTo-JSON -AsArray -Compress)" >> $env:GITHUB_OUTPUT 88 | env: 89 | BUILD_AUTO_FAKEITEASY: ${{ inputs.buildAutoFakeItEasy }} 90 | BUILD_AUTO_MOQ: ${{ inputs.buildAutoMoq }} 91 | BUILD_AUTO_NSUBSTITUTE: ${{ inputs.buildAutoNSubstitute }} 92 | - name: 🎱 determine next version 93 | id: determine-version 94 | uses: ./.github/actions/determine-next-version 95 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.Core.Tests/SpecimenBuilders/RandomExceptValuesGeneratorTests.cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.Core.Tests.SpecimenBuilders 2 | { 3 | using System; 4 | 5 | using global::AutoFixture; 6 | using global::AutoFixture.Kernel; 7 | 8 | using Moq; 9 | 10 | using Objectivity.AutoFixture.XUnit2.Core.Requests; 11 | using Objectivity.AutoFixture.XUnit2.Core.SpecimenBuilders; 12 | 13 | using Xunit; 14 | 15 | [Collection("RandomExceptValuesGenerator")] 16 | [Trait("Category", "SpecimenBuilders")] 17 | public class RandomExceptValuesGeneratorTests 18 | { 19 | [Fact(DisplayName = "GIVEN uninitialized context WHEN Create is invoked THEN exception is thrown")] 20 | public void GivenUninitializedContext_WhenCreateIsInvoked_ThenExceptionIsThrown() 21 | { 22 | // Arrange 23 | var builder = new RandomExceptValuesGenerator(); 24 | 25 | // Act 26 | object Act() => builder.Create(new object(), null); 27 | 28 | // Assert 29 | var exception = Assert.Throws(Act); 30 | Assert.Equal("context", exception.ParamName); 31 | } 32 | 33 | [Fact(DisplayName = "GIVEN uninitialized request WHEN Create is invoked THEN exception is thrown")] 34 | public void GivenUninitializedRequest_WhenCreateIsInvoked_ThenExceptionIsThrown() 35 | { 36 | // Arrange 37 | var builder = new RandomExceptValuesGenerator(); 38 | var context = new Mock(); 39 | 40 | // Act 41 | object Act() => builder.Create(null, context.Object); 42 | 43 | // Assert 44 | var exception = Assert.Throws(Act); 45 | Assert.Equal("request", exception.ParamName); 46 | } 47 | 48 | [Fact(DisplayName = "GIVEN excluded value and context which resolves to the same value WHEN Create is invoked THEN exception is thrown")] 49 | public void GivenExcludedValueAndContextWhichResolvesToTheSameValue_WhenCreateIsInvoked_ThenExceptionIsThrown() 50 | { 51 | // Arrange 52 | var builder = new RandomExceptValuesGenerator(); 53 | var context = new Mock(); 54 | const int duplicateValue = 5; 55 | context.Setup(x => x.Resolve(It.IsNotNull())).Returns(duplicateValue); 56 | var request = new ExceptValuesRequest(duplicateValue.GetType(), duplicateValue); 57 | 58 | // Act 59 | object Act() => builder.Create(request, context.Object); 60 | 61 | // Assert 62 | var exception = Assert.Throws(Act); 63 | Assert.NotNull(exception.Message); 64 | Assert.NotEmpty(exception.Message); 65 | } 66 | 67 | [Fact(DisplayName = "GIVEN unsupported request WHEN Create is invoked THEN NoSpecimen is returned")] 68 | public void GivenUnsupportedRequest_WhenCreateIsInvoked_ThenNoSpecimenIsReturned() 69 | { 70 | // Arrange 71 | var builder = new RandomExceptValuesGenerator(); 72 | var context = new Mock(); 73 | var request = typeof(string); 74 | 75 | // Act 76 | var result = builder.Create(request, context.Object); 77 | 78 | // Assert 79 | Assert.NotNull(result); 80 | Assert.IsType(result); 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /.github/workflows/cicd.yml: -------------------------------------------------------------------------------- 1 | name: '♻️ CI/CD' 2 | 3 | on: 4 | pull_request: 5 | paths: 6 | - 'GitVersion.yml' 7 | - 'src/**' 8 | - '!src/qodana.yml' 9 | - '.github/actions/**' 10 | - '.github/workflows/**' 11 | - '!.github/workflows/codeql.yml' 12 | - '!.github/workflows/fossa-scan.yml' 13 | - '!.github/workflows/qodana.yml' 14 | - '!.github/workflows/semgrep.yml' 15 | - '!.github/workflows/snyk.yml' 16 | types: [opened, synchronize, reopened] 17 | push: 18 | branches: 19 | - 'master' 20 | paths: 21 | - 'GitVersion.yml' 22 | - 'src/**' 23 | - '!src/qodana.yml' 24 | - '.github/actions/**' 25 | - '.github/workflows/**' 26 | - '!.github/workflows/codeql.yml' 27 | - '!.github/workflows/fossa-scan.yml' 28 | - '!.github/workflows/qodana.yml' 29 | - '!.github/workflows/semgrep.yml' 30 | - '!.github/workflows/snyk.yml' 31 | workflow_dispatch: 32 | inputs: 33 | buildAutoFakeItEasy: 34 | description: 'Build AutoFakeItEasy' 35 | required: true 36 | type: boolean 37 | default: true 38 | buildAutoMoq: 39 | description: 'Build AutoMoq' 40 | required: true 41 | type: boolean 42 | default: true 43 | buildAutoNSubstitute: 44 | description: 'Build AutoNSubstitute' 45 | required: true 46 | type: boolean 47 | default: true 48 | environment: 49 | description: 'Environment' 50 | type: environment 51 | required: true 52 | default: prod 53 | 54 | defaults: 55 | run: 56 | shell: pwsh 57 | 58 | concurrency: 59 | group: ${{ github.workflow }}-${{ github.ref }} 60 | cancel-in-progress: true 61 | 62 | jobs: 63 | init: 64 | permissions: 65 | contents: read 66 | uses: ./.github/workflows/init.yml 67 | with: 68 | buildAutoFakeItEasy: ${{github.event_name != 'workflow_dispatch' || inputs.buildAutoFakeItEasy == true}} 69 | buildAutoMoq: ${{github.event_name != 'workflow_dispatch' || inputs.buildAutoMoq == true}} 70 | buildAutoNSubstitute: ${{github.event_name != 'workflow_dispatch' || inputs.buildAutoNSubstitute == true}} 71 | 72 | build-test-pack: 73 | needs: [init] 74 | if: ${{ needs.init.outputs.modules != '' }} 75 | permissions: 76 | contents: read 77 | strategy: 78 | matrix: 79 | module-name: ${{ fromJSON(needs.init.outputs.modules) }} 80 | uses: ./.github/workflows/build-test-pack.yml 81 | with: 82 | configuration: ${{ needs.init.outputs.configuration }} 83 | module-name: ${{ matrix.module-name }} 84 | module-namespace: ${{ needs.init.outputs.namespace }} 85 | version: ${{ needs.init.outputs.version }} 86 | secrets: 87 | signing-key-value: ${{ secrets.SIGNING_KEY }} 88 | codecov-token: ${{ secrets.CODECOV_TOKEN }} 89 | 90 | publish: 91 | needs: [build-test-pack] 92 | if: ${{ inputs.environment != null }} 93 | permissions: 94 | packages: write 95 | uses: ./.github/workflows/publish.yml 96 | with: 97 | environment: ${{ inputs.environment }} 98 | secrets: inherit 99 | 100 | tag: 101 | needs: [publish, init] 102 | # Allow tagging only on the master branch when publish was successful 103 | if: ${{ github.ref_name == 'master' && needs.publish.result == 'success' }} 104 | permissions: 105 | contents: write 106 | uses: ./.github/workflows/tag.yml 107 | with: 108 | version: ${{ needs.init.outputs.version }} 109 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.Core/Attributes/MemberAutoDataBaseAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.Core.Attributes 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Globalization; 6 | using System.Linq; 7 | using System.Reflection; 8 | 9 | using global::AutoFixture; 10 | 11 | using Objectivity.AutoFixture.XUnit2.Core.Common; 12 | using Objectivity.AutoFixture.XUnit2.Core.Customizations; 13 | using Objectivity.AutoFixture.XUnit2.Core.MemberData; 14 | using Objectivity.AutoFixture.XUnit2.Core.Providers; 15 | 16 | using Xunit; 17 | using Xunit.Sdk; 18 | 19 | [AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = true)] 20 | [DataDiscoverer("Xunit.Sdk.MemberDataDiscoverer", "xunit.core")] 21 | public abstract class MemberAutoDataBaseAttribute : MemberDataAttributeBase 22 | { 23 | protected MemberAutoDataBaseAttribute(IFixture fixture, string memberName, params object[] parameters) 24 | : base(memberName.NotNull(nameof(memberName)), parameters) 25 | { 26 | this.Fixture = fixture.NotNull(nameof(fixture)); 27 | } 28 | 29 | public IFixture Fixture { get; } 30 | 31 | /// 32 | /// Gets or sets a value indicating whether virtual members should be ignored during object creation. 33 | /// 34 | /// Indicates whether virtual members should be ignored during object creation. 35 | public bool IgnoreVirtualMembers { get; set; } 36 | 37 | /// 38 | /// Gets or sets a value indicating whether to share a fixture across all data items; true by default. 39 | /// 40 | /// Indicates whether to share a fixture across all data items; true by default. 41 | public bool ShareFixture { get; set; } = true; 42 | 43 | public override IEnumerable GetData(MethodInfo testMethod) 44 | { 45 | // Customize shared fixture 46 | this.CustomizeFixture(this.Fixture); 47 | 48 | return base.GetData(testMethod)?.Select(values => this.ExtendDataItem(testMethod, values)); 49 | } 50 | 51 | protected override object[] ConvertDataItem(MethodInfo testMethod, object item) 52 | { 53 | if (item is object[] objArray) 54 | { 55 | return objArray; 56 | } 57 | 58 | var message = string.Format( 59 | CultureInfo.InvariantCulture, 60 | "Property {0} on {1} yielded an item that is not an object[]", 61 | this.MemberName, 62 | this.RetrieveMemberType(testMethod)); 63 | 64 | throw new ArgumentException(message); 65 | } 66 | 67 | protected abstract IFixture Customize(IFixture fixture); 68 | 69 | protected abstract IAutoFixtureInlineAttributeProvider CreateProvider(); 70 | 71 | private IFixture CustomizeFixture(IFixture fixture) 72 | { 73 | fixture.Customize(new AutoDataCommonCustomization(this.IgnoreVirtualMembers)); 74 | return this.Customize(fixture); 75 | } 76 | 77 | private object[] ExtendDataItem(MethodInfo testMethod, object[] values) 78 | { 79 | var fixture = this.ShareFixture 80 | ? this.Fixture 81 | : this.CustomizeFixture(new Fixture()); 82 | 83 | var converter = new MemberAutoDataItemExtender(fixture, this.CreateProvider()); 84 | 85 | return converter.Extend(testMethod, values); 86 | } 87 | 88 | private Type RetrieveMemberType(MethodInfo testMethod) 89 | { 90 | return this.MemberType 91 | ?? testMethod.NotNull(nameof(testMethod)).DeclaringType; 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.Core.Tests/Common/RoundRobinEnumerableTests.cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.Core.Tests.Common 2 | { 3 | using System; 4 | using System.Collections; 5 | using System.Linq; 6 | 7 | using global::AutoFixture.Xunit2; 8 | 9 | using Objectivity.AutoFixture.XUnit2.Core.Common; 10 | 11 | using Xunit; 12 | 13 | [Collection("RoundRobinEnumerable")] 14 | [Trait("Category", "Common")] 15 | public class RoundRobinEnumerableTests 16 | { 17 | [Fact(DisplayName = "GIVEN uninitialized argument WHEN constructor is invoked THEN exception is thrown")] 18 | public void GivenUninitializedArgument_WhenConstructorIsInvoked_ThenExceptionIsThrown() 19 | { 20 | // Arrange 21 | // Act 22 | static object Act() => new RoundRobinEnumerable(null); 23 | 24 | // Assert 25 | var exception = Assert.Throws(Act); 26 | Assert.Equal("values", exception.ParamName); 27 | } 28 | 29 | [Fact(DisplayName = "GIVEN no arguments WHEN constructor is invoked THEN exception is thrown")] 30 | public void GivenNoArguments_WhenConstructorIsInvoked_ThenExceptionIsThrown() 31 | { 32 | // Arrange 33 | // Act 34 | static object Act() => new RoundRobinEnumerable(); 35 | 36 | // Assert 37 | var exception = Assert.Throws(Act); 38 | Assert.NotNull(exception.Message); 39 | Assert.NotEmpty(exception.Message); 40 | Assert.Contains("At least one value", exception.Message); 41 | } 42 | 43 | [AutoData] 44 | [Theory(DisplayName = "GIVEN round robin with values WHEN Current is invoked after construction THEN exception is thrown")] 45 | public void GivenRoundRobinWithValues_WhenCurrentIsInvokedAfterConstruction_ThenExceptionIsThrown( 46 | int[] values) 47 | { 48 | // Arrange 49 | IEnumerator enumerator = new RoundRobinEnumerable(values); 50 | 51 | // Act 52 | object Act() => enumerator.Current; 53 | 54 | // Assert 55 | var exception = Assert.Throws(Act); 56 | Assert.NotNull(exception.Message); 57 | Assert.NotEmpty(exception.Message); 58 | Assert.Contains("initial position", exception.Message); 59 | } 60 | 61 | [AutoData] 62 | [Theory(DisplayName = "GIVEN round robin with values WHEN Current is invoked after reset THEN exception is thrown")] 63 | public void GivenRoundRobinWithValues_WhenCurrentIsInvokedAfterReset_ThenExceptionIsThrown( 64 | int[] values) 65 | { 66 | // Arrange 67 | IEnumerator enumerator = new RoundRobinEnumerable(values); 68 | 69 | // Act 70 | enumerator.MoveNext(); 71 | enumerator.Reset(); 72 | object Act() => enumerator.Current; 73 | 74 | // Assert 75 | var exception = Assert.Throws(Act); 76 | Assert.NotNull(exception.Message); 77 | Assert.NotEmpty(exception.Message); 78 | Assert.Contains("initial position", exception.Message); 79 | } 80 | 81 | [AutoData] 82 | [Theory(DisplayName = "GIVEN round robin with values WHEN enumerating twice THEN ordered values enumerated twice")] 83 | public void GivenRoundRobinWithValues_WhenEnumeratingTwice_ThenOrderedValuesEnumeratedTwice( 84 | int[] values) 85 | { 86 | // Arrange 87 | var enumerator = new RoundRobinEnumerable(values); 88 | var duplicatedValues = values.Concat(values.ToArray()).ToArray(); 89 | 90 | // Act 91 | var items = duplicatedValues.Select(x => 92 | { 93 | var canMove = enumerator.MoveNext(); 94 | return canMove && enumerator.Current == x; 95 | }).ToArray(); 96 | 97 | // Assert 98 | Assert.All(items, Assert.True); 99 | Assert.Equal(duplicatedValues.Length, items.Length); 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.AutoNSubstitute.Tests/Attributes/AutoMockDataAttributeTests.cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.AutoNSubstitute.Tests.Attributes 2 | { 3 | using System.Collections.Generic; 4 | using System.Reflection; 5 | 6 | using global::AutoFixture; 7 | using global::AutoFixture.AutoNSubstitute; 8 | using global::AutoFixture.Xunit2; 9 | using NSubstitute; 10 | 11 | using Objectivity.AutoFixture.XUnit2.AutoNSubstitute.Attributes; 12 | using Objectivity.AutoFixture.XUnit2.Core.Customizations; 13 | using Objectivity.AutoFixture.XUnit2.Core.Providers; 14 | 15 | using Xunit; 16 | using Xunit.Sdk; 17 | 18 | [Collection("AutoMockDataAttribute")] 19 | [Trait("Category", "DataAttribute")] 20 | public class AutoMockDataAttributeTests 21 | { 22 | [Fact(DisplayName = "WHEN parameterless constructor is invoked THEN fixture and attribute provider are created")] 23 | public void WhenParameterlessConstructorIsInvoked_ThenFixtureAndAttributeProviderAreCreated() 24 | { 25 | // Arrange 26 | // Act 27 | var attribute = new AutoMockDataAttribute(); 28 | 29 | // Assert 30 | Assert.NotNull(attribute.Fixture); 31 | Assert.NotNull(attribute.Provider); 32 | Assert.False(attribute.IgnoreVirtualMembers); 33 | } 34 | 35 | [InlineAutoData(true)] 36 | [InlineAutoData(false)] 37 | [Theory(DisplayName = "WHEN GetData is invoked THEN fixture is configured and data returned")] 38 | public void WhenGetDataIsInvoked_ThenFixtureIsConfiguredAndDataReturned(bool ignoreVirtualMembers) 39 | { 40 | // Arrange 41 | var data = new[] 42 | { 43 | new object[] { 1, 2, 3 }, 44 | new object[] { 4, 5, 6 }, 45 | new object[] { 7, 8, 9 }, 46 | }; 47 | var fixture = Substitute.For(); 48 | var customizations = new List(); 49 | fixture.Customize(Arg.Do(customizations.Add)) 50 | .Returns(fixture); 51 | var dataAttribute = Substitute.For(); 52 | dataAttribute.GetData(Arg.Any()).Returns(data); 53 | var provider = Substitute.For(); 54 | provider.GetAttribute(Arg.Any()).Returns(dataAttribute); 55 | var attribute = new AutoMockDataAttribute(fixture, provider) 56 | { 57 | IgnoreVirtualMembers = ignoreVirtualMembers, 58 | }; 59 | var methodInfo = typeof(AutoMockDataAttributeTests).GetMethod(nameof(this.MethodUnderTest), BindingFlags.Instance | BindingFlags.NonPublic); 60 | 61 | // Act 62 | var result = attribute.GetData(methodInfo); 63 | 64 | // Assert 65 | Assert.Same(data, result); 66 | provider.Received(1).GetAttribute(Arg.Any()); 67 | dataAttribute.Received(1).GetData(Arg.Any()); 68 | 69 | Assert.Equal(2, customizations.Count); 70 | var customization = Assert.IsType(customizations[0]); 71 | Assert.Equal(ignoreVirtualMembers, customization.IgnoreVirtualMembers); 72 | Assert.IsType(customizations[1]); 73 | } 74 | 75 | [AutoMockData] 76 | [Theory(DisplayName = "GIVEN test method has some value parameters WHEN test run THEN parameters are generated")] 77 | public void GivenTestMethodHasSomeValueParameters_WhenTestRun_ThenParametersAreGenerated(int value) 78 | { 79 | // Arrange 80 | // Act 81 | // Assert 82 | Assert.NotEqual(0, value); 83 | } 84 | 85 | [AutoMockData] 86 | [Theory(DisplayName = "GIVEN test method has some object parameters WHEN test run THEN parameters are generated")] 87 | public void GivenTestMethodHasSomeObjectParameters_WhenTestRun_ThenParametersAreGenerated(IFakeObjectUnderTest value) 88 | { 89 | // Arrange 90 | // Act 91 | // Assert 92 | Assert.NotNull(value); 93 | Assert.NotNull(value.StringProperty); 94 | Assert.NotEmpty(value.StringProperty); 95 | } 96 | 97 | protected void MethodUnderTest() 98 | { 99 | // Empty method under test 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /.github/workflows/build-test-pack.yml: -------------------------------------------------------------------------------- 1 | name: '🏗️ Build, test & pack' 2 | 3 | on: 4 | workflow_call: 5 | inputs: 6 | configuration: 7 | description: Name of the configuration 8 | required: true 9 | type: string 10 | module-name: 11 | description: Name of the module 12 | required: true 13 | type: string 14 | module-namespace: 15 | description: Name of the module namespace 16 | required: true 17 | type: string 18 | version: 19 | description: Assembly and package version 20 | required: true 21 | type: string 22 | secrets: 23 | codecov-token: 24 | description: Value of Codecov token used to upload code coverage results 25 | required: true 26 | signing-key-value: 27 | description: Value of the signing key 28 | required: true 29 | 30 | env: 31 | DOTNET_NOLOGO: true 32 | DOTNET_CLI_TELEMETRY_OPTOUT: true 33 | NUGET_PACKAGES: ${{ github.workspace }}\.nuget\packages 34 | Version: ${{ inputs.version }} 35 | Configuration: ${{ inputs.configuration }} 36 | 37 | defaults: 38 | run: 39 | shell: pwsh 40 | 41 | jobs: 42 | run: 43 | runs-on: windows-latest # We are using windows instead of ubuntu becaus it provides support for net472 & net48. 44 | timeout-minutes: 15 45 | permissions: 46 | contents: read 47 | steps: 48 | - name: 📥 checkout 49 | uses: actions/checkout@v6 50 | with: 51 | fetch-depth: 0 52 | - name: 🖊️ materialize signing key 53 | id: signing-key 54 | uses: ./.github/actions/materialize-signing-key 55 | with: 56 | signing-key-value: ${{ secrets.signing-key-value }} 57 | - name: 💾 cache nuget packages 58 | uses: actions/cache@v5 59 | with: 60 | path: ${{ env.NUGET_PACKAGES }} 61 | key: ${{ runner.os }}-nuget-${{ inputs.module-name }}-${{ hashFiles('**/*.csproj') }} 62 | restore-keys: | 63 | ${{ runner.os }}-nuget-${{ inputs.module-name }} 64 | - name: 🏗️ build 65 | run: | 66 | $ErrorActionPreference = 'stop' 67 | dotnet build ./src/${env:MODULE_NAMESPACE}.${env:MODULE_NAME}.sln 68 | if ($LastExitCode -ne 0) { 69 | throw "dotnet build failed with exit code $LastExitCode" 70 | } 71 | env: 72 | MODULE_NAMESPACE: ${{ inputs.module-namespace }} 73 | MODULE_NAME: ${{ inputs.module-name }} 74 | StrongNameKey: ${{ secrets.signing-key-value }} 75 | StrongNameKeyPath: ${{ steps.signing-key.outputs.file-path }} 76 | - name: 🧪 test ${{ inputs.module-name }} in [net472, net48] 77 | run: | 78 | $ErrorActionPreference = 'stop' 79 | dotnet test ./src/${env:MODULE_NAMESPACE}.${env:MODULE_NAME}.Tests/ --no-build -f net472 80 | if ($LastExitCode -ne 0) { 81 | throw "dotnet test failed with exit code $LastExitCode" 82 | } 83 | 84 | dotnet test ./src/${env:MODULE_NAMESPACE}.${env:MODULE_NAME}.Tests/ --no-build -f net48 85 | if ($LastExitCode -ne 0) { 86 | throw "dotnet test failed with exit code $LastExitCode" 87 | } 88 | env: 89 | MODULE_NAMESPACE: ${{ inputs.module-namespace }} 90 | MODULE_NAME: ${{ inputs.module-name }} 91 | - name: 🧪 test ${{ inputs.module-name }} in net8.0 & collect coverage 92 | uses: ./.github/actions/test-and-collect-coverage 93 | with: 94 | codecov-token: ${{ secrets.codecov-token }} 95 | module-name: ${{ inputs.module-name }} 96 | module-namespace: ${{ inputs.module-namespace }} 97 | target-framework: net8.0 98 | - name: 📦 pack 99 | if: ${{ startsWith(inputs.module-name, 'Auto' ) }} 100 | run: | 101 | $ErrorActionPreference = 'stop' 102 | dotnet pack ./src/${env:MODULE_NAMESPACE}.${env:MODULE_NAME} 103 | if ($LastExitCode -ne 0) { 104 | throw "dotnet pack failed with exit code $LastExitCode" 105 | } 106 | env: 107 | MODULE_NAMESPACE: ${{ inputs.module-namespace }} 108 | MODULE_NAME: ${{ inputs.module-name }} 109 | StrongNameKey: ${{ secrets.signing-key-value }} 110 | StrongNameKeyPath: ${{ steps.signing-key.outputs.file-path }} 111 | - name: 🔼 upload packages 112 | if: ${{ startsWith(inputs.module-name, 'Auto' ) }} 113 | uses: actions/upload-artifact@v6 114 | with: 115 | name: packages-${{ inputs.module-name }} 116 | path: | 117 | ./src/**/*.nupkg 118 | ./src/**/*.snupkg 119 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.AutoMoq.Tests/Attributes/AutoMockDataAttributeTests.cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.AutoMoq.Tests.Attributes 2 | { 3 | using System.Collections.Generic; 4 | using System.Reflection; 5 | 6 | using global::AutoFixture; 7 | using global::AutoFixture.AutoMoq; 8 | using global::AutoFixture.Xunit2; 9 | using Moq; 10 | 11 | using Objectivity.AutoFixture.XUnit2.AutoMoq.Attributes; 12 | using Objectivity.AutoFixture.XUnit2.Core.Customizations; 13 | using Objectivity.AutoFixture.XUnit2.Core.Providers; 14 | 15 | using Xunit; 16 | using Xunit.Sdk; 17 | 18 | [Collection("AutoMockDataAttribute")] 19 | [Trait("Category", "DataAttribute")] 20 | public class AutoMockDataAttributeTests 21 | { 22 | [Fact(DisplayName = "WHEN parameterless constructor is invoked THEN fixture and attribute provider are created")] 23 | public void WhenParameterlessConstructorIsInvoked_ThenFixtureAndAttributeProviderAreCreated() 24 | { 25 | // Arrange 26 | // Act 27 | var attribute = new AutoMockDataAttribute(); 28 | 29 | // Assert 30 | Assert.NotNull(attribute.Fixture); 31 | Assert.NotNull(attribute.Provider); 32 | Assert.False(attribute.IgnoreVirtualMembers); 33 | } 34 | 35 | [InlineAutoData(true)] 36 | [InlineAutoData(false)] 37 | [Theory(DisplayName = "WHEN GetData is invoked THEN fixture is configured and data returned")] 38 | public void WhenGetDataIsInvoked_ThenFixtureIsConfiguredAndDataReturned(bool ignoreVirtualMembers) 39 | { 40 | // Arrange 41 | var data = new[] 42 | { 43 | new object[] { 1, 2, 3 }, 44 | new object[] { 4, 5, 6 }, 45 | new object[] { 7, 8, 9 }, 46 | }; 47 | var fixture = new Mock(); 48 | var customizations = new List(); 49 | fixture.Setup(x => x.Customize(It.IsAny())) 50 | .Callback(customizations.Add) 51 | .Returns(fixture.Object); 52 | var dataAttribute = new Mock(); 53 | dataAttribute.Setup(a => a.GetData(It.IsAny())).Returns(data); 54 | var provider = new Mock(); 55 | provider.Setup(p => p.GetAttribute(It.IsAny())).Returns(dataAttribute.Object); 56 | var attribute = new AutoMockDataAttribute(fixture.Object, provider.Object) 57 | { 58 | IgnoreVirtualMembers = ignoreVirtualMembers, 59 | }; 60 | var methodInfo = typeof(AutoMockDataAttributeTests).GetMethod(nameof(this.MethodUnderTest), BindingFlags.Instance | BindingFlags.NonPublic); 61 | 62 | // Act 63 | var result = attribute.GetData(methodInfo); 64 | 65 | // Assert 66 | Assert.Same(data, result); 67 | provider.VerifyAll(); 68 | dataAttribute.VerifyAll(); 69 | 70 | Assert.Equal(2, customizations.Count); 71 | var customization = Assert.IsType(customizations[0]); 72 | Assert.Equal(ignoreVirtualMembers, customization.IgnoreVirtualMembers); 73 | Assert.IsType(customizations[1]); 74 | } 75 | 76 | [AutoMockData] 77 | [Theory(DisplayName = "GIVEN test method has some value parameters WHEN test run THEN parameters are generated")] 78 | public void GivenTestMethodHasSomeValueParameters_WhenTestRun_ThenParametersAreGenerated(int value) 79 | { 80 | // Arrange 81 | // Act 82 | // Assert 83 | Assert.NotEqual(0, value); 84 | } 85 | 86 | [AutoMockData] 87 | [Theory(DisplayName = "GIVEN test method has some object parameters WHEN test run THEN parameters are generated")] 88 | public void GivenTestMethodHasSomeObjectParameters_WhenTestRun_ThenParametersAreGenerated(IFakeObjectUnderTest value) 89 | { 90 | // Arrange 91 | // Act 92 | // Assert 93 | Assert.NotNull(value); 94 | Assert.NotNull(value.StringProperty); 95 | Assert.NotEmpty(value.StringProperty); 96 | } 97 | 98 | protected void MethodUnderTest() 99 | { 100 | // Empty method under test 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.AutoFakeItEasy.Tests/Attributes/AutoMockDataAttributeTests.cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.AutoFakeItEasy.Tests.Attributes 2 | { 3 | using System.Collections.Generic; 4 | using System.Reflection; 5 | 6 | using FakeItEasy; 7 | 8 | using global::AutoFixture; 9 | using global::AutoFixture.AutoFakeItEasy; 10 | using global::AutoFixture.Xunit2; 11 | using Objectivity.AutoFixture.XUnit2.AutoFakeItEasy.Attributes; 12 | using Objectivity.AutoFixture.XUnit2.Core.Customizations; 13 | using Objectivity.AutoFixture.XUnit2.Core.Providers; 14 | 15 | using Xunit; 16 | using Xunit.Sdk; 17 | 18 | [Collection("AutoMockDataAttribute")] 19 | [Trait("Category", "DataAttribute")] 20 | public class AutoMockDataAttributeTests 21 | { 22 | [Fact(DisplayName = "WHEN parameterless constructor is invoked THEN fixture and attribute provider are created")] 23 | public void WhenParameterlessConstructorIsInvoked_ThenFixtureAndAttributeProviderAreCreated() 24 | { 25 | // Arrange 26 | // Act 27 | var attribute = new AutoMockDataAttribute(); 28 | 29 | // Assert 30 | Assert.NotNull(attribute.Fixture); 31 | Assert.NotNull(attribute.Provider); 32 | Assert.False(attribute.IgnoreVirtualMembers); 33 | } 34 | 35 | [InlineAutoData(true)] 36 | [InlineAutoData(false)] 37 | [Theory(DisplayName = "WHEN GetData is invoked THEN fixture is configured and data returned")] 38 | public void WhenGetDataIsInvoked_ThenFixtureIsConfiguredAndDataReturned(bool ignoreVirtualMembers) 39 | { 40 | // Arrange 41 | var data = new[] 42 | { 43 | new object[] { 1, 2, 3 }, 44 | new object[] { 4, 5, 6 }, 45 | new object[] { 7, 8, 9 }, 46 | }; 47 | var fixture = A.Fake(); 48 | var customizations = new List(); 49 | A.CallTo(() => fixture.Customize(A._)) 50 | .Invokes((ICustomization customization) => customizations.Add(customization)) 51 | .Returns(fixture); 52 | var dataAttribute = A.Fake(); 53 | A.CallTo(() => dataAttribute.GetData(A._)).Returns(data); 54 | var provider = A.Fake(); 55 | A.CallTo(() => provider.GetAttribute(A._)).Returns(dataAttribute); 56 | var attribute = new AutoMockDataAttribute(fixture, provider) 57 | { 58 | IgnoreVirtualMembers = ignoreVirtualMembers, 59 | }; 60 | var methodInfo = typeof(AutoMockDataAttributeTests).GetMethod(nameof(this.MethodUnderTest), BindingFlags.Instance | BindingFlags.NonPublic); 61 | 62 | // Act 63 | var result = attribute.GetData(methodInfo); 64 | 65 | // Assert 66 | Assert.Same(data, result); 67 | A.CallTo(() => provider.GetAttribute(A._)).MustHaveHappenedOnceExactly(); 68 | A.CallTo(() => dataAttribute.GetData(A._)).MustHaveHappenedOnceExactly(); 69 | 70 | Assert.Equal(2, customizations.Count); 71 | var customization = Assert.IsType(customizations[0]); 72 | Assert.Equal(ignoreVirtualMembers, customization.IgnoreVirtualMembers); 73 | Assert.IsType(customizations[1]); 74 | } 75 | 76 | [AutoMockData] 77 | [Theory(DisplayName = "GIVEN test method has some value parameters WHEN test run THEN parameters are generated")] 78 | public void GivenTestMethodHasSomeValueParameters_WhenTestRun_ThenParametersAreGenerated(int value) 79 | { 80 | // Arrange 81 | // Act 82 | // Assert 83 | Assert.NotEqual(0, value); 84 | } 85 | 86 | [AutoMockData] 87 | [Theory(DisplayName = "GIVEN test method has some object parameters WHEN test run THEN parameters are generated")] 88 | public void GivenTestMethodHasSomeObjectParameters_WhenTestRun_ThenParametersAreGenerated(IFakeObjectUnderTest value) 89 | { 90 | // Arrange 91 | // Act 92 | // Assert 93 | Assert.NotNull(value); 94 | Assert.NotNull(value.StringProperty); 95 | Assert.NotEmpty(value.StringProperty); 96 | } 97 | 98 | protected void MethodUnderTest() 99 | { 100 | // Empty method under test 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.Core.Tests/MemberData/MemberAutoDataItemExtenderTests.cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.Core.Tests.MemberData 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Reflection; 7 | 8 | using global::AutoFixture; 9 | 10 | using Moq; 11 | 12 | using Objectivity.AutoFixture.XUnit2.Core.MemberData; 13 | using Objectivity.AutoFixture.XUnit2.Core.Providers; 14 | 15 | using Xunit; 16 | using Xunit.Sdk; 17 | 18 | [Collection("MemberAutoDataItemConverter")] 19 | [Trait("Category", "MemberData")] 20 | public class MemberAutoDataItemExtenderTests 21 | { 22 | private static readonly MethodInfo TestMethod = typeof(MemberAutoDataItemExtenderTests).GetMethod(nameof(MethodUnderTest), BindingFlags.Instance | BindingFlags.NonPublic); 23 | private readonly Fixture fixture = new(); 24 | private readonly Mock dataAttributeProvider = new(); 25 | private readonly Mock dataAttribute = new(); 26 | private readonly IDataItemExtender converter; 27 | 28 | public MemberAutoDataItemExtenderTests() 29 | { 30 | var data = this.fixture.Create>(); 31 | this.dataAttributeProvider.Setup(p => p.GetAttribute(this.fixture, It.IsAny())).Returns(this.dataAttribute.Object); 32 | this.dataAttribute.Setup(a => a.GetData(It.IsAny())).Returns(data); 33 | this.converter = new MemberAutoDataItemExtender(this.fixture, this.dataAttributeProvider.Object); 34 | } 35 | 36 | [Fact(DisplayName = "GIVEN provider with no data attribute WHEN Convert is invoked THEN Null is returned")] 37 | public void GivenProviderWithNoDataAttribute_WhenConvertIsInvoked_ThenNullReturned() 38 | { 39 | // Arrange 40 | var noData = Enumerable.Empty(); 41 | var noDataAttribute = new Mock(); 42 | noDataAttribute.Setup(a => a.GetData(It.IsAny())).Returns(noData); 43 | var noDataProvider = new Mock(); 44 | noDataProvider.Setup(x => x.GetAttribute(It.IsAny(), It.IsNotNull())).Returns(noDataAttribute.Object); 45 | var noDataConverter = new MemberAutoDataItemExtender(this.fixture, noDataProvider.Object); 46 | var item = this.fixture.Create(); 47 | 48 | // Act 49 | var data = noDataConverter.Extend(TestMethod, item); 50 | 51 | // Assert 52 | Assert.Null(data); 53 | noDataProvider.VerifyAll(); 54 | noDataAttribute.VerifyAll(); 55 | } 56 | 57 | [Fact(DisplayName = "GIVEN valid parameters WHEN Convert is invoked THEN appropriate code is invoked and data is returned")] 58 | public void GivenValidParameters_WhenConvertIsInvoked_ThenAppropriateCodeIsInvokedAndDataIsReturned() 59 | { 60 | // Arrange 61 | var item = this.fixture.Create(); 62 | 63 | // Act 64 | var data = this.converter.Extend(TestMethod, item); 65 | 66 | // Assert 67 | Assert.NotNull(data); 68 | this.dataAttributeProvider.VerifyAll(); 69 | this.dataAttribute.VerifyAll(); 70 | } 71 | 72 | [Fact(DisplayName = "GIVEN uninitialized item WHEN Convert is invoked THEN Null is returned")] 73 | public void GivenUninitializedItem_WhenConvertInvoked_ThenNullReturned() 74 | { 75 | // Arrange 76 | const object[] item = null; 77 | 78 | // Act 79 | var data = this.converter.Extend(TestMethod, item); 80 | 81 | // Assert 82 | Assert.Null(data); 83 | } 84 | 85 | [Fact(DisplayName = "GIVEN uninitialized test method WHEN Convert is invoked THEN exception is thrown")] 86 | public void GivenUninitializedTestMethod_WhenConvertIsInvoked_ThenExceptionIsThrown() 87 | { 88 | // Arrange 89 | const MethodInfo method = null; 90 | var item = this.fixture.Create(); 91 | 92 | // Act 93 | object Act() => this.converter.Extend(method, item); 94 | 95 | // Assert 96 | var exception = Assert.Throws(Act); 97 | Assert.Equal("testMethod", exception.ParamName); 98 | } 99 | 100 | protected void MethodUnderTest() 101 | { 102 | // Empty method under test 103 | } 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.Core.Tests/Common/EnumerableExtensionsTests.cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.Core.Tests.Common 2 | { 3 | using System; 4 | using System.Collections; 5 | using System.Collections.Generic; 6 | using System.Diagnostics.CodeAnalysis; 7 | 8 | using global::AutoFixture.Xunit2; 9 | 10 | using Objectivity.AutoFixture.XUnit2.Core.Common; 11 | 12 | using Xunit; 13 | 14 | [Collection("EnumerableExtensions")] 15 | [Trait("Category", "Common")] 16 | public class EnumerableExtensionsTests 17 | { 18 | [Fact(DisplayName = "GIVEN uninitialized argument WHEN TryGetEnumerableSingleTypeArgument is invoked THEN exception is thrown")] 19 | [SuppressMessage("ReSharper", "UnusedVariable", Justification = "This is good enougth to test the logic.")] 20 | public void GivenUninitializedArgument_WhenTryGetEnumerableSingleTypeArgumentIsInvoked_ThenExceptionIsThrown() 21 | { 22 | // Arrange 23 | Type enumerableType = null; 24 | 25 | // Act 26 | object Act() => enumerableType.TryGetEnumerableSingleTypeArgument(out _); 27 | 28 | // Assert 29 | var exception = Assert.Throws(Act); 30 | Assert.Equal("type", exception.ParamName); 31 | } 32 | 33 | [InlineData(typeof(int[]), typeof(int))] 34 | [InlineData(typeof(List), typeof(int))] 35 | [InlineData(typeof(Dictionary), typeof(KeyValuePair))] 36 | [InlineData(typeof(IEnumerable), typeof(int))] 37 | [Theory(DisplayName = "GIVEN valid collection WHEN TryGetEnumerableSingleTypeArgument is invoked THEN collection single type argument returned")] 38 | public void GivenValidCollection_WhenTryGetEnumerableSingleTypeArgumentIsInvoked_ThenCollectionSingleTypeArgumentReturned(Type enumerableType, Type expectedType) 39 | { 40 | // Arrange 41 | // Act 42 | var isSuccessful = enumerableType.TryGetEnumerableSingleTypeArgument(out var itemType); 43 | 44 | // Assert 45 | Assert.True(isSuccessful); 46 | Assert.Equal(expectedType, itemType); 47 | } 48 | 49 | [InlineData(typeof(Tuple))] 50 | [InlineData(typeof(IEnumerable))] 51 | [Theory(DisplayName = "GIVEN invalid collection WHEN TryGetEnumerableSingleTypeArgument is invoked THEN no argument returned")] 52 | public void GivenInvalidCollection_WhenTryGetEnumerableSingleTypeArgumentIsInvoked_ThenNoArgumentReturned(Type enumerableType) 53 | { 54 | // Arrange 55 | // Act 56 | var isSuccessful = enumerableType.TryGetEnumerableSingleTypeArgument(out _); 57 | 58 | // Assert 59 | Assert.False(isSuccessful); 60 | } 61 | 62 | [Fact(DisplayName = "GIVEN generic definition collection WHEN TryGetEnumerableSingleTypeArgument is invoked THEN no argument returned")] 63 | public void GivenGenericDefinitionCollection_WhenTryGetEnumerableSingleTypeArgumentIsInvoked_ThenNoArgumentReturned() 64 | { 65 | // Arrange 66 | var enumerableType = typeof(IEnumerable).GetGenericTypeDefinition(); 67 | 68 | // Act 69 | var isSuccessful = enumerableType.TryGetEnumerableSingleTypeArgument(out _); 70 | 71 | // Assert 72 | Assert.False(isSuccessful); 73 | } 74 | 75 | [InlineData(null, typeof(int), "items")] 76 | [InlineData(new[] { 1 }, null, "itemType")] 77 | [Theory(DisplayName = "GIVEN uninitialized argument WHEN ToTypedArray is invoked THEN exception is thrown")] 78 | public void GivenUninitializedArgument_WhenToTypedArrayIsInvoked_ThenExceptionIsThrown( 79 | IEnumerable items, 80 | Type itemType, 81 | string exceptionParamName) 82 | { 83 | // Arrange 84 | // Act 85 | object Act() => items.ToTypedArray(itemType); 86 | 87 | // Assert 88 | var exception = Assert.Throws(Act); 89 | Assert.Equal(exceptionParamName, exception.ParamName); 90 | } 91 | 92 | [AutoData] 93 | [Theory(DisplayName = "GIVEN typed enumerable WHEN ToTypedArray is invoked THEN array is returned")] 94 | public void GivenTypedEnumerable_WhenToTypedArrayIsInvoked_ThenArrayIsReturned(int[] items) 95 | { 96 | // Arrange 97 | var itemType = typeof(int); 98 | 99 | // Act 100 | var array = items.ToTypedArray(itemType); 101 | 102 | // Assert 103 | Assert.Equal(items, array); 104 | Assert.True(array.GetType().IsArray); 105 | } 106 | 107 | [AutoData] 108 | [Theory(DisplayName = "GIVEN enumerable WHEN ToTypedArray is invoked THEN array is returned")] 109 | public void GivenEnumerable_WhenToTypedArrayIsInvoked_ThenArrayIsReturned(BitArray items) 110 | { 111 | // Arrange 112 | var itemType = typeof(bool); 113 | 114 | // Act 115 | var array = items.ToTypedArray(itemType); 116 | 117 | // Assert 118 | Assert.Equal(items, array); 119 | } 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.Core.Tests/Attributes/MemberAutoDataBaseAttributeTests.cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.Core.Tests.Attributes 2 | { 3 | using System; 4 | using System.Reflection; 5 | 6 | using global::AutoFixture; 7 | using global::AutoFixture.Xunit2; 8 | using Moq; 9 | 10 | using Objectivity.AutoFixture.XUnit2.Core.Attributes; 11 | using Objectivity.AutoFixture.XUnit2.Core.Providers; 12 | 13 | using Xunit; 14 | 15 | [Collection("MemberAutoDataBaseAttribute")] 16 | [Trait("Category", "DataAttribute")] 17 | public class MemberAutoDataBaseAttributeTests 18 | { 19 | private static readonly Type MemberType = typeof(MemberAutoDataBaseAttributeTests); 20 | private static readonly MethodInfo TestMethod = MemberType.GetMethod(nameof(MethodUnderTest), BindingFlags.Instance | BindingFlags.NonPublic); 21 | 22 | public static TheoryData MemberTypeTestData { get; } = new() 23 | { 24 | { MemberType, MemberType.Name }, 25 | { typeof(string), nameof(String) }, 26 | { null, MemberType.Name }, 27 | }; 28 | 29 | public static TheoryData NullTheoryData => null; 30 | 31 | [AutoData] 32 | [Theory(DisplayName = "GIVEN uninitialized fixture WHEN constructor is invoked THEN exception is thrown")] 33 | public void GivenUninitializedFixture_WhenConstructorIsInvoked_ThenExceptionIsThrown(string memberName) 34 | { 35 | // Arrange 36 | const IFixture fixture = null; 37 | var provider = new Mock(); 38 | 39 | // Act 40 | object Act() => new MemberAutoDataBaseAttributeUnderTest(fixture, memberName, provider.Object); 41 | 42 | // Assert 43 | var exception = Assert.Throws(Act); 44 | Assert.Equal("fixture", exception.ParamName); 45 | } 46 | 47 | [MemberData(nameof(MemberTypeTestData))] 48 | [Theory(DisplayName = "GIVEN item of unexpected type WHEN ConvertDataItem is invoked THEN exception is thrown")] 49 | public void GivenItemOfUnexpectedType_WhenConvertDataItemIsInvoked_ThenExceptionIsThrown( 50 | Type memberType, 51 | string expectedTypeName) 52 | { 53 | // Arrange 54 | var fixture = new Fixture(); 55 | var memberName = fixture.Create(); 56 | var item = fixture.Create(); 57 | var attribute = new MemberAutoDataBaseAttributeUnderTest(fixture, memberName) { MemberType = memberType }; 58 | 59 | // Act 60 | object[] Act() => attribute.CallConvertDataItem(TestMethod, item); 61 | 62 | // Assert 63 | var exception = Assert.Throws((Func)Act); 64 | Assert.NotNull(exception.Message); 65 | Assert.NotEmpty(exception.Message); 66 | Assert.Contains(memberName, exception.Message); 67 | Assert.Contains(expectedTypeName, exception.Message); 68 | } 69 | 70 | [Fact(DisplayName = "GIVEN array WHEN ConvertDataItem is invoked THEN the same array is returned")] 71 | public void GivenArray_WhenConvertDataItemIsInvoked_ThenTheSameArrayIsReturned() 72 | { 73 | // Arrange 74 | var fixture = new Fixture(); 75 | var array = fixture.Create(); 76 | var attribute = new MemberAutoDataBaseAttributeUnderTest(fixture, nameof(NullTheoryData)); 77 | 78 | // Act 79 | var data = attribute.CallConvertDataItem(TestMethod, array); 80 | 81 | // Assert 82 | Assert.Equal(array, data); 83 | } 84 | 85 | [Fact(DisplayName = "GIVEN null theory data WHEN GetData is invoked THEN null is returned")] 86 | public void GivenNullItem_WhenGetDataIsInvoked_ThenNullIsReturned() 87 | { 88 | // Arrange 89 | var fixture = new Fixture(); 90 | var attribute = new MemberAutoDataBaseAttributeUnderTest(fixture, nameof(NullTheoryData)); 91 | 92 | // Act 93 | var data = attribute.GetData(TestMethod); 94 | 95 | // Assert 96 | Assert.Null(data); 97 | } 98 | 99 | protected void MethodUnderTest() 100 | { 101 | // Empty method under test 102 | } 103 | 104 | [AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = true)] 105 | private sealed class MemberAutoDataBaseAttributeUnderTest : MemberAutoDataBaseAttribute 106 | { 107 | public MemberAutoDataBaseAttributeUnderTest(IFixture fixture, string memberName, params object[] parameters) 108 | : base(fixture, memberName, parameters) 109 | { 110 | } 111 | 112 | public object[] CallConvertDataItem(MethodInfo testMethod, object item) => this.ConvertDataItem(testMethod, item); 113 | 114 | protected override IAutoFixtureInlineAttributeProvider CreateProvider() 115 | { 116 | throw new NotImplementedException(); 117 | } 118 | 119 | protected override IFixture Customize(IFixture fixture) 120 | { 121 | return fixture; 122 | } 123 | } 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.AutoMock.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.7.34202.233 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Objectivity.AutoFixture.XUnit2.Core", "Objectivity.AutoFixture.XUnit2.Core\Objectivity.AutoFixture.XUnit2.Core.csproj", "{7FF963AD-E151-4E45-9093-7B9E6441BFA0}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Objectivity.AutoFixture.XUnit2.Core.Tests", "Objectivity.AutoFixture.XUnit2.Core.Tests\Objectivity.AutoFixture.XUnit2.Core.Tests.csproj", "{D8F331D4-CE28-4BC8-92A0-3DA512E8FCFF}" 9 | EndProject 10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Objectivity.AutoFixture.XUnit2.AutoFakeItEasy", "Objectivity.AutoFixture.XUnit2.AutoFakeItEasy\Objectivity.AutoFixture.XUnit2.AutoFakeItEasy.csproj", "{FA941947-5694-4084-9A75-B0F17D7672B8}" 11 | EndProject 12 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Objectivity.AutoFixture.XUnit2.AutoFakeItEasy.Tests", "Objectivity.AutoFixture.XUnit2.AutoFakeItEasy.Tests\Objectivity.AutoFixture.XUnit2.AutoFakeItEasy.Tests.csproj", "{57BD0984-1649-488B-9535-D54DE1882231}" 13 | EndProject 14 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Objectivity.AutoFixture.XUnit2.AutoMoq", "Objectivity.AutoFixture.XUnit2.AutoMoq\Objectivity.AutoFixture.XUnit2.AutoMoq.csproj", "{576A5EF1-A0D6-485B-AB2D-C050A23B79F8}" 15 | EndProject 16 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Objectivity.AutoFixture.XUnit2.AutoMoq.Tests", "Objectivity.AutoFixture.XUnit2.AutoMoq.Tests\Objectivity.AutoFixture.XUnit2.AutoMoq.Tests.csproj", "{75AFB615-C843-4C9A-AF9A-9A71FBAACAAE}" 17 | EndProject 18 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Objectivity.AutoFixture.XUnit2.AutoNSubstitute", "Objectivity.AutoFixture.XUnit2.AutoNSubstitute\Objectivity.AutoFixture.XUnit2.AutoNSubstitute.csproj", "{809E0EFD-A1D7-4B5A-A101-788A8D82B063}" 19 | EndProject 20 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Objectivity.AutoFixture.XUnit2.AutoNSubstitute.Tests", "Objectivity.AutoFixture.XUnit2.AutoNSubstitute.Tests\Objectivity.AutoFixture.XUnit2.AutoNSubstitute.Tests.csproj", "{D83CDAEE-2166-4A3F-9640-AAFED4DFC5D3}" 21 | EndProject 22 | Global 23 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 24 | Debug|Any CPU = Debug|Any CPU 25 | Release|Any CPU = Release|Any CPU 26 | EndGlobalSection 27 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 28 | {7FF963AD-E151-4E45-9093-7B9E6441BFA0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 29 | {7FF963AD-E151-4E45-9093-7B9E6441BFA0}.Debug|Any CPU.Build.0 = Debug|Any CPU 30 | {7FF963AD-E151-4E45-9093-7B9E6441BFA0}.Release|Any CPU.ActiveCfg = Release|Any CPU 31 | {7FF963AD-E151-4E45-9093-7B9E6441BFA0}.Release|Any CPU.Build.0 = Release|Any CPU 32 | {D8F331D4-CE28-4BC8-92A0-3DA512E8FCFF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 33 | {D8F331D4-CE28-4BC8-92A0-3DA512E8FCFF}.Debug|Any CPU.Build.0 = Debug|Any CPU 34 | {D8F331D4-CE28-4BC8-92A0-3DA512E8FCFF}.Release|Any CPU.ActiveCfg = Release|Any CPU 35 | {D8F331D4-CE28-4BC8-92A0-3DA512E8FCFF}.Release|Any CPU.Build.0 = Release|Any CPU 36 | {FA941947-5694-4084-9A75-B0F17D7672B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 37 | {FA941947-5694-4084-9A75-B0F17D7672B8}.Debug|Any CPU.Build.0 = Debug|Any CPU 38 | {FA941947-5694-4084-9A75-B0F17D7672B8}.Release|Any CPU.ActiveCfg = Release|Any CPU 39 | {FA941947-5694-4084-9A75-B0F17D7672B8}.Release|Any CPU.Build.0 = Release|Any CPU 40 | {57BD0984-1649-488B-9535-D54DE1882231}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 41 | {57BD0984-1649-488B-9535-D54DE1882231}.Debug|Any CPU.Build.0 = Debug|Any CPU 42 | {57BD0984-1649-488B-9535-D54DE1882231}.Release|Any CPU.ActiveCfg = Release|Any CPU 43 | {57BD0984-1649-488B-9535-D54DE1882231}.Release|Any CPU.Build.0 = Release|Any CPU 44 | {576A5EF1-A0D6-485B-AB2D-C050A23B79F8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 45 | {576A5EF1-A0D6-485B-AB2D-C050A23B79F8}.Debug|Any CPU.Build.0 = Debug|Any CPU 46 | {576A5EF1-A0D6-485B-AB2D-C050A23B79F8}.Release|Any CPU.ActiveCfg = Release|Any CPU 47 | {576A5EF1-A0D6-485B-AB2D-C050A23B79F8}.Release|Any CPU.Build.0 = Release|Any CPU 48 | {75AFB615-C843-4C9A-AF9A-9A71FBAACAAE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 49 | {75AFB615-C843-4C9A-AF9A-9A71FBAACAAE}.Debug|Any CPU.Build.0 = Debug|Any CPU 50 | {75AFB615-C843-4C9A-AF9A-9A71FBAACAAE}.Release|Any CPU.ActiveCfg = Release|Any CPU 51 | {75AFB615-C843-4C9A-AF9A-9A71FBAACAAE}.Release|Any CPU.Build.0 = Release|Any CPU 52 | {809E0EFD-A1D7-4B5A-A101-788A8D82B063}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 53 | {809E0EFD-A1D7-4B5A-A101-788A8D82B063}.Debug|Any CPU.Build.0 = Debug|Any CPU 54 | {809E0EFD-A1D7-4B5A-A101-788A8D82B063}.Release|Any CPU.ActiveCfg = Release|Any CPU 55 | {809E0EFD-A1D7-4B5A-A101-788A8D82B063}.Release|Any CPU.Build.0 = Release|Any CPU 56 | {D83CDAEE-2166-4A3F-9640-AAFED4DFC5D3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 57 | {D83CDAEE-2166-4A3F-9640-AAFED4DFC5D3}.Debug|Any CPU.Build.0 = Debug|Any CPU 58 | {D83CDAEE-2166-4A3F-9640-AAFED4DFC5D3}.Release|Any CPU.ActiveCfg = Release|Any CPU 59 | {D83CDAEE-2166-4A3F-9640-AAFED4DFC5D3}.Release|Any CPU.Build.0 = Release|Any CPU 60 | EndGlobalSection 61 | GlobalSection(SolutionProperties) = preSolution 62 | HideSolutionNode = FALSE 63 | EndGlobalSection 64 | GlobalSection(ExtensibilityGlobals) = postSolution 65 | SolutionGuid = {565D276E-8621-4E85-98F6-1C6432F7693D} 66 | EndGlobalSection 67 | EndGlobal 68 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.Core.Tests/SpecimenBuilders/RandomFixedValuesGeneratorTests.cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.Core.Tests.SpecimenBuilders 2 | { 3 | using System; 4 | using System.Linq; 5 | 6 | using global::AutoFixture; 7 | using global::AutoFixture.Kernel; 8 | using global::AutoFixture.Xunit2; 9 | using Moq; 10 | 11 | using Objectivity.AutoFixture.XUnit2.Core.Requests; 12 | using Objectivity.AutoFixture.XUnit2.Core.SpecimenBuilders; 13 | 14 | using Xunit; 15 | 16 | [Collection("RandomFixedValuesGenerator")] 17 | [Trait("Category", "SpecimenBuilders")] 18 | public class RandomFixedValuesGeneratorTests 19 | { 20 | [Fact(DisplayName = "GIVEN uninitialized context WHEN Create is invoked THEN exception is thrown")] 21 | public void GivenUninitializedContext_WhenCreateIsInvoked_ThenExceptionIsThrown() 22 | { 23 | // Arrange 24 | var builder = new RandomFixedValuesGenerator(); 25 | 26 | // Act 27 | object Act() => builder.Create(new object(), null); 28 | 29 | // Assert 30 | var exception = Assert.Throws(Act); 31 | Assert.Equal("context", exception.ParamName); 32 | } 33 | 34 | [Fact(DisplayName = "GIVEN uninitialized request WHEN Create is invoked THEN exception is thrown")] 35 | public void GivenUninitializedRequest_WhenCreateIsInvoked_ThenExceptionIsThrown() 36 | { 37 | // Arrange 38 | var builder = new RandomFixedValuesGenerator(); 39 | var context = new Mock(); 40 | 41 | // Act 42 | object Act() => builder.Create(null, context.Object); 43 | 44 | // Assert 45 | var exception = Assert.Throws(Act); 46 | Assert.Equal("request", exception.ParamName); 47 | } 48 | 49 | [Fact(DisplayName = "GIVEN unsupported request WHEN Create is invoked THEN NoSpecimen is returned")] 50 | public void GivenUnsupportedRequest_WhenCreateIsInvoked_ThenNoSpecimenIsReturned() 51 | { 52 | // Arrange 53 | var builder = new RandomFixedValuesGenerator(); 54 | var context = new Mock(); 55 | var request = typeof(string); 56 | 57 | // Act 58 | var result = builder.Create(request, context.Object); 59 | 60 | // Assert 61 | Assert.NotNull(result); 62 | Assert.IsType(result); 63 | } 64 | 65 | [Fact(DisplayName = "GIVEN request with many values WHEN Create is invoked many times THEN only defined values are returned")] 66 | public void GivenRequestWithManyValues_WhenCreateIsInvokedManyTimes_ThenOnlyDefinedValuesAreReturned() 67 | { 68 | // Arrange 69 | var builder = new RandomFixedValuesGenerator(); 70 | var context = new Mock(); 71 | var expectedValues = new object[] { 1, 2 }; 72 | var request = new FixedValuesRequest(typeof(int), expectedValues); 73 | 74 | // Act 75 | var result = Enumerable.Range(0, 10).Select((_) => (int)builder.Create(request, context.Object)).ToList(); 76 | 77 | // Assert 78 | Assert.NotNull(result); 79 | Assert.Equal(10, result.Count); 80 | Assert.All(result, x => Assert.Contains(x, expectedValues)); 81 | } 82 | 83 | [AutoData] 84 | [Theory(DisplayName = "GIVEN request with single value WHEN Create is invoked many times THEN only repeated defined value is returned")] 85 | internal void GivenRequestWithSingleValue_WhenCreateIsInvokedManyTimes_ThenOnlyRepeatedDefinedValueIsReturned( 86 | RandomFixedValuesGenerator builder, 87 | IFixture fixture) 88 | { 89 | // Arrange 90 | var context = new Mock(); 91 | var expectedValue = fixture.Create(); 92 | var request = new FixedValuesRequest(typeof(int), expectedValue); 93 | 94 | // Act 95 | var result = Enumerable.Range(0, 10).Select((_) => (int)builder.Create(request, context.Object)).ToList(); 96 | 97 | // Assert 98 | Assert.NotNull(result); 99 | Assert.Equal(10, result.Count); 100 | Assert.All(result, x => Assert.Equal(expectedValue, x)); 101 | } 102 | 103 | [AutoData] 104 | [Theory(DisplayName = "GIVEN many requests WHEN Create is invoked per each request THEN different defined value are returned")] 105 | internal void GivenManyRequests_WhenCreateIsInvokedPerEachRequest_ThenDifferentDefinedValueAreReturned( 106 | RandomFixedValuesGenerator builder) 107 | { 108 | // Arrange 109 | var context = new Mock(); 110 | var setup = new[] { 1, 2 }.ToDictionary( 111 | x => x, 112 | x => new FixedValuesRequest(typeof(int), x)); 113 | 114 | // Act 115 | var result = setup.Select(x => (int)builder.Create(x.Value, context.Object)).ToArray(); 116 | 117 | // Assert 118 | Assert.Equal(setup.First().Key, result.First()); 119 | Assert.Equal(setup.Last().Key, result.Last()); 120 | } 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.Core.Tests/Attributes/InlineAutoDataBaseAttributeTests.cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.Core.Tests.Attributes 2 | { 3 | using System; 4 | 5 | using global::AutoFixture; 6 | using global::AutoFixture.Xunit2; 7 | using Moq; 8 | 9 | using Objectivity.AutoFixture.XUnit2.Core.Attributes; 10 | using Objectivity.AutoFixture.XUnit2.Core.Providers; 11 | 12 | using Xunit; 13 | 14 | [Collection("InlineAutoDataBaseAttribute")] 15 | [Trait("Category", "DataAttribute")] 16 | public class InlineMockDataBaseAttributeTests 17 | { 18 | [AutoData] 19 | [Theory(DisplayName = "GIVEN existing fixture and attribute provider WHEN constructor is invoked THEN has fixture attribute provider and no values")] 20 | public void GivenExistingFixtureAndAttributeProvider_WhenConstructorIsInvoked_ThenHasFixtureAttributeProviderAndNoValues(Fixture fixture) 21 | { 22 | // Arrange 23 | var provider = new Mock(); 24 | 25 | // Act 26 | var attribute = new InlineAutoDataBaseAttributeUnderTest(fixture, provider.Object); 27 | 28 | // Assert 29 | Assert.Equal(fixture, attribute.Fixture); 30 | Assert.False(attribute.IgnoreVirtualMembers); 31 | Assert.Equal(provider.Object, attribute.Provider); 32 | Assert.Empty(attribute.Values); 33 | } 34 | 35 | [AutoData] 36 | [Theory(DisplayName = "GIVEN existing fixture, attribute provider and values WHEN constructor is invoked THEN has specified fixture, attribute provider and values")] 37 | public void GivenExistingFixtureAttributeProviderAndValues_WhenConstructorIsInvoked_ThenHasSpecifiedFixtureAttributeProviderAndValues(Fixture fixture) 38 | { 39 | // Arrange 40 | var provider = new Mock(); 41 | var initialValues = new[] { "test", 1, new object() }; 42 | 43 | // Act 44 | var attribute = new InlineAutoDataBaseAttributeUnderTest(fixture, provider.Object, initialValues[0], initialValues[1], initialValues[2]); 45 | 46 | // Assert 47 | Assert.Equal(fixture, attribute.Fixture); 48 | Assert.False(attribute.IgnoreVirtualMembers); 49 | Assert.Equal(provider.Object, attribute.Provider); 50 | Assert.Equal(initialValues, attribute.Values); 51 | } 52 | 53 | [AutoData] 54 | [Theory(DisplayName = "GIVEN existing fixture, attribute provider and uninitialized values WHEN constructor is invoked THEN has specified fixture, attribute provider and no values")] 55 | public void GivenExistingFixtureAttributeProviderAndUninitializedValues_WhenConstructorIsInvoked_ThenHasSpecifiedFixtureAttributeProviderAndNoValues(Fixture fixture) 56 | { 57 | // Arrange 58 | var provider = new Mock(); 59 | const object[] initialValues = null; 60 | 61 | // Act 62 | var attribute = new InlineAutoDataBaseAttributeUnderTest(fixture, provider.Object, initialValues); 63 | 64 | // Assert 65 | Assert.Equal(fixture, attribute.Fixture); 66 | Assert.False(attribute.IgnoreVirtualMembers); 67 | Assert.Equal(provider.Object, attribute.Provider); 68 | Assert.Empty(attribute.Values); 69 | } 70 | 71 | [Fact(DisplayName = "GIVEN uninitialized fixture WHEN constructor is invoked THEN exception is thrown")] 72 | public void GivenUninitializedFixture_WhenConstructorIsInvoked_ThenExceptionIsThrown() 73 | { 74 | // Arrange 75 | const Fixture fixture = null; 76 | var provider = new Mock(); 77 | 78 | // Act 79 | object Act() => new InlineAutoDataBaseAttributeUnderTest(fixture, provider.Object); 80 | 81 | // Assert 82 | var exception = Assert.Throws(Act); 83 | Assert.Equal("fixture", exception.ParamName); 84 | } 85 | 86 | [AutoData] 87 | [Theory(DisplayName = "GIVEN uninitialized attribute provider WHEN constructor is invoked THEN exception is thrown")] 88 | public void GivenUninitializedAttributeProvider_WhenConstructorIsInvoked_ThenExceptionIsThrown(Fixture fixture) 89 | { 90 | // Arrange 91 | const IAutoFixtureInlineAttributeProvider provider = null; 92 | 93 | // Act 94 | object Act() => new InlineAutoDataBaseAttributeUnderTest(fixture, provider); 95 | 96 | // Assert 97 | var exception = Assert.Throws(Act); 98 | Assert.Equal("provider", exception.ParamName); 99 | } 100 | 101 | [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] 102 | private sealed class InlineAutoDataBaseAttributeUnderTest : InlineAutoDataBaseAttribute 103 | { 104 | public InlineAutoDataBaseAttributeUnderTest(IFixture fixture, IAutoFixtureInlineAttributeProvider provider, params object[] values) 105 | : base(fixture, provider, values) 106 | { 107 | } 108 | 109 | protected override IFixture Customize(IFixture fixture) 110 | { 111 | throw new NotImplementedException(); 112 | } 113 | } 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.Core/Objectivity.AutoFixture.XUnit2.Core.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0;netstandard2.1 5 | $(TargetFrameworks);net472;net48 6 | true 7 | true 8 | 9 | NU1901;NU1902;NU1903;NU1904 10 | latest 11 | All 12 | true 13 | true 14 | true 15 | true 16 | snupkg 17 | true 18 | latest 19 | false 20 | true 21 | 22 | 23 | 24 | false 25 | 26 | 27 | 28 | true 29 | 30 | true 31 | 32 | ..\public.snk 33 | $(StrongNameKeyPath) 34 | 35 | 36 | 37 | 46 | true 47 | $(NoWarn),1573,1591,1712,AD0001 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | all 71 | runtime; build; native; contentfiles; analyzers; buildtransitive 72 | 73 | 74 | all 75 | runtime; build; native; contentfiles; analyzers; buildtransitive 76 | 77 | 78 | all 79 | runtime; build; native; contentfiles; analyzers; buildtransitive 80 | 81 | 82 | all 83 | runtime; build; native; contentfiles; analyzers; buildtransitive 84 | 85 | 86 | all 87 | runtime; build; native; contentfiles; analyzers; buildtransitive 88 | 89 | 90 | all 91 | runtime; build; native; contentfiles; analyzers; buildtransitive 92 | 93 | 94 | runtime; build; native; contentfiles; analyzers 95 | all 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.AutoNSubstitute.Tests/Attributes/InlineAutoMockDataAttributeTests.cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.AutoNSubstitute.Tests.Attributes 2 | { 3 | using System.Collections.Generic; 4 | using System.Reflection; 5 | 6 | using global::AutoFixture; 7 | using global::AutoFixture.AutoNSubstitute; 8 | using global::AutoFixture.Xunit2; 9 | using NSubstitute; 10 | 11 | using Objectivity.AutoFixture.XUnit2.AutoNSubstitute.Attributes; 12 | using Objectivity.AutoFixture.XUnit2.Core.Customizations; 13 | using Objectivity.AutoFixture.XUnit2.Core.Providers; 14 | 15 | using Xunit; 16 | using Xunit.Sdk; 17 | 18 | [Collection("InlineAutoMockDataAttribute")] 19 | [Trait("Category", "DataAttribute")] 20 | public class InlineAutoMockDataAttributeTests 21 | { 22 | [Fact(DisplayName = "WHEN parameterless constructor is invoked THEN has no values but fixture and attribute provider are created")] 23 | public void WhenParameterlessConstructorIsInvoked_ThenHasNoValuesButFixtureAndAttributeProviderAreCreated() 24 | { 25 | // Arrange 26 | // Act 27 | var attribute = new InlineAutoMockDataAttribute(); 28 | 29 | // Assert 30 | Assert.NotNull(attribute.Fixture); 31 | Assert.False(attribute.IgnoreVirtualMembers); 32 | Assert.NotNull(attribute.Provider); 33 | Assert.Empty(attribute.Values); 34 | } 35 | 36 | [Fact(DisplayName = "GIVEN existing inline values WHEN constructor is invoked THEN has specified values and fixture and attribute provider are created")] 37 | public void GivenExistingInlineValues_WhenConstructorIsInvoked_ThenHasSpecifiedValuesAndFixtureAndAttributeProviderAreCreated() 38 | { 39 | // Arrange 40 | var initialValues = new[] { "test", 1, new object() }; 41 | 42 | // Act 43 | var attribute = new InlineAutoMockDataAttribute(initialValues[0], initialValues[1], initialValues[2]); 44 | 45 | // Assert 46 | Assert.NotNull(attribute.Fixture); 47 | Assert.False(attribute.IgnoreVirtualMembers); 48 | Assert.NotNull(attribute.Provider); 49 | Assert.Equal(initialValues, attribute.Values); 50 | } 51 | 52 | [Fact(DisplayName = "GIVEN uninitialized values WHEN constructor is invoked THEN has no values and fixture and attribute provider are created")] 53 | public void GivenUninitializedValues_WhenConstructorIsInvoked_ThenHasNoValuesAndFixtureAndAttributeProviderAreCreated() 54 | { 55 | // Arrange 56 | const object[] initialValues = null; 57 | 58 | // Act 59 | var attribute = new InlineAutoMockDataAttribute(initialValues); 60 | 61 | // Assert 62 | Assert.NotNull(attribute.Fixture); 63 | Assert.False(attribute.IgnoreVirtualMembers); 64 | Assert.NotNull(attribute.Provider); 65 | Assert.Empty(attribute.Values); 66 | } 67 | 68 | [InlineAutoData(true)] 69 | [InlineAutoData(false)] 70 | [Theory(DisplayName = "WHEN GetData is invoked THEN fixture is configured and data returned")] 71 | public void WhenGetDataIsInvoked_ThenFixtureIsConfiguredAndDataReturned(bool ignoreVirtualMembers) 72 | { 73 | // Arrange 74 | var data = new[] 75 | { 76 | new object[] { 1, 2, 3 }, 77 | new object[] { 4, 5, 6 }, 78 | new object[] { 7, 8, 9 }, 79 | }; 80 | var fixture = Substitute.For(); 81 | var customizations = new List(); 82 | fixture.Customize(Arg.Do(customizations.Add)) 83 | .Returns(fixture); 84 | var dataAttribute = Substitute.For(); 85 | dataAttribute.GetData(Arg.Any()).Returns(data); 86 | var provider = Substitute.For(); 87 | provider.GetAttribute(Arg.Any()).Returns(dataAttribute); 88 | var attribute = new InlineAutoMockDataAttribute(fixture, provider) 89 | { 90 | IgnoreVirtualMembers = ignoreVirtualMembers, 91 | }; 92 | var methodInfo = typeof(InlineAutoMockDataAttributeTests).GetMethod(nameof(this.MethodUnderTest), BindingFlags.Instance | BindingFlags.NonPublic); 93 | 94 | // Act 95 | var result = attribute.GetData(methodInfo); 96 | 97 | // Assert 98 | Assert.Same(data, result); 99 | provider.Received(1).GetAttribute(Arg.Any()); 100 | dataAttribute.Received(1).GetData(Arg.Any()); 101 | 102 | Assert.Equal(2, customizations.Count); 103 | var customization = Assert.IsType(customizations[0]); 104 | Assert.Equal(ignoreVirtualMembers, customization.IgnoreVirtualMembers); 105 | Assert.IsType(customizations[1]); 106 | } 107 | 108 | [InlineAutoMockData(100)] 109 | [Theory(DisplayName = "GIVEN test method has some inline parameters WHEN test run THEN parameters are generated")] 110 | public void GivenTestMethodHasSomeInlineParameters_WhenTestRun_ThenParametersAreGenerated( 111 | int firstValueInstance, 112 | int secondValueInstance, 113 | IFakeObjectUnderTest objectInstance) 114 | { 115 | // Arrange 116 | // Act 117 | // Assert 118 | Assert.Equal(100, firstValueInstance); 119 | Assert.NotEqual(0, secondValueInstance); 120 | 121 | Assert.NotNull(objectInstance); 122 | Assert.NotNull(objectInstance.StringProperty); 123 | Assert.NotEmpty(objectInstance.StringProperty); 124 | } 125 | 126 | protected void MethodUnderTest() 127 | { 128 | // Empty method under test 129 | } 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /src/Objectivity.AutoFixture.XUnit2.AutoMoq.Tests/Attributes/InlineAutoMockDataAttributeTests.cs: -------------------------------------------------------------------------------- 1 | namespace Objectivity.AutoFixture.XUnit2.AutoMoq.Tests.Attributes 2 | { 3 | using System.Collections.Generic; 4 | using System.Reflection; 5 | 6 | using global::AutoFixture; 7 | using global::AutoFixture.AutoMoq; 8 | using global::AutoFixture.Xunit2; 9 | using Moq; 10 | 11 | using Objectivity.AutoFixture.XUnit2.AutoMoq.Attributes; 12 | using Objectivity.AutoFixture.XUnit2.Core.Customizations; 13 | using Objectivity.AutoFixture.XUnit2.Core.Providers; 14 | 15 | using Xunit; 16 | using Xunit.Sdk; 17 | 18 | [Collection("InlineAutoMockDataAttribute")] 19 | [Trait("Category", "DataAttribute")] 20 | public class InlineAutoMockDataAttributeTests 21 | { 22 | [Fact(DisplayName = "WHEN parameterless constructor is invoked THEN has no values but fixture and attribute provider are created")] 23 | public void WhenParameterlessConstructorIsInvoked_ThenHasNoValuesButFixtureAndAttributeProviderAreCreated() 24 | { 25 | // Arrange 26 | // Act 27 | var attribute = new InlineAutoMockDataAttribute(); 28 | 29 | // Assert 30 | Assert.NotNull(attribute.Fixture); 31 | Assert.False(attribute.IgnoreVirtualMembers); 32 | Assert.NotNull(attribute.Provider); 33 | Assert.Empty(attribute.Values); 34 | } 35 | 36 | [Fact(DisplayName = "GIVEN existing inline values WHEN constructor is invoked THEN has specified values and fixture and attribute provider are created")] 37 | public void GivenExistingInlineValues_WhenConstructorIsInvoked_ThenHasSpecifiedValuesAndFixtureAndAttributeProviderAreCreated() 38 | { 39 | // Arrange 40 | var initialValues = new[] { "test", 1, new object() }; 41 | 42 | // Act 43 | var attribute = new InlineAutoMockDataAttribute(initialValues[0], initialValues[1], initialValues[2]); 44 | 45 | // Assert 46 | Assert.NotNull(attribute.Fixture); 47 | Assert.False(attribute.IgnoreVirtualMembers); 48 | Assert.NotNull(attribute.Provider); 49 | Assert.Equal(initialValues, attribute.Values); 50 | } 51 | 52 | [Fact(DisplayName = "GIVEN uninitialized values WHEN constructor is invoked THEN has no values and fixture and attribute provider are created")] 53 | public void GivenUninitializedValues_WhenConstructorIsInvoked_ThenHasNoValuesAndFixtureAndAttributeProviderAreCreated() 54 | { 55 | // Arrange 56 | const object[] initialValues = null; 57 | 58 | // Act 59 | var attribute = new InlineAutoMockDataAttribute(initialValues); 60 | 61 | // Assert 62 | Assert.NotNull(attribute.Fixture); 63 | Assert.False(attribute.IgnoreVirtualMembers); 64 | Assert.NotNull(attribute.Provider); 65 | Assert.Empty(attribute.Values); 66 | } 67 | 68 | [InlineAutoData(true)] 69 | [InlineAutoData(false)] 70 | [Theory(DisplayName = "WHEN GetData is invoked THEN fixture is configured and data returned")] 71 | public void WhenGetDataIsInvoked_ThenFixtureIsConfiguredAndDataReturned(bool ignoreVirtualMembers) 72 | { 73 | // Arrange 74 | var data = new[] 75 | { 76 | new object[] { 1, 2, 3 }, 77 | new object[] { 4, 5, 6 }, 78 | new object[] { 7, 8, 9 }, 79 | }; 80 | var fixture = new Mock(); 81 | var customizations = new List(); 82 | fixture.Setup(x => x.Customize(It.IsAny())) 83 | .Callback(customizations.Add) 84 | .Returns(fixture.Object); 85 | var dataAttribute = new Mock(); 86 | dataAttribute.Setup(a => a.GetData(It.IsAny())).Returns(data); 87 | var provider = new Mock(); 88 | provider.Setup(p => p.GetAttribute(It.IsAny())).Returns(dataAttribute.Object); 89 | var attribute = new InlineAutoMockDataAttribute(fixture.Object, provider.Object) 90 | { 91 | IgnoreVirtualMembers = ignoreVirtualMembers, 92 | }; 93 | var methodInfo = typeof(InlineAutoMockDataAttributeTests).GetMethod(nameof(this.MethodUnderTest), BindingFlags.Instance | BindingFlags.NonPublic); 94 | 95 | // Act 96 | var result = attribute.GetData(methodInfo); 97 | 98 | // Assert 99 | Assert.Same(data, result); 100 | provider.VerifyAll(); 101 | dataAttribute.VerifyAll(); 102 | 103 | Assert.Equal(2, customizations.Count); 104 | var customization = Assert.IsType(customizations[0]); 105 | Assert.Equal(ignoreVirtualMembers, customization.IgnoreVirtualMembers); 106 | Assert.IsType(customizations[1]); 107 | } 108 | 109 | [InlineAutoMockData(100)] 110 | [Theory(DisplayName = "GIVEN test method has some inline parameters WHEN test run THEN parameters are generated")] 111 | public void GivenTestMethodHasSomeInlineParameters_WhenTestRun_ThenParametersAreGenerated( 112 | int firstValueInstance, 113 | int secondValueInstance, 114 | IFakeObjectUnderTest objectInstance) 115 | { 116 | // Arrange 117 | // Act 118 | // Assert 119 | Assert.Equal(100, firstValueInstance); 120 | Assert.NotEqual(0, secondValueInstance); 121 | 122 | Assert.NotNull(objectInstance); 123 | Assert.NotNull(objectInstance.StringProperty); 124 | Assert.NotEmpty(objectInstance.StringProperty); 125 | } 126 | 127 | protected void MethodUnderTest() 128 | { 129 | // Empty method under test 130 | } 131 | } 132 | } 133 | --------------------------------------------------------------------------------