From 64b15f8cc1767ba9e4f06ce26a1345d34f59cbdf Mon Sep 17 00:00:00 2001
From: Piotr Zajac
Date: Wed, 22 Apr 2026 07:51:41 +0200
Subject: [PATCH 1/3] refactor(tests): consolidate duplicate Facts into
Theories
Replace pairs of [Fact] methods that tested the same behaviour with
different inputs with a single [Theory] using [InlineData] or
[MemberData]/TheoryData. Affected files: RandomFixedValuesGeneratorTests,
RandomExceptValuesGeneratorTests, ValuesRequestTests,
RequestFactoryRelayTests, and EnumerableExtensionsTests.
Co-Authored-By: Claude Sonnet 4.6
---
...nsolidate-duplicate-Facts-into-Theories.md | 19 +
dotnet-tools.json | 2 +-
.../Common/EnumerableExtensionsTests.cs | 235 +++++-----
.../Requests/ValuesRequestTests.cs | 32 +-
.../RandomExceptValuesGeneratorTests.cs | 158 ++++---
.../RandomFixedValuesGeneratorTests.cs | 236 +++++-----
.../RequestFactoryRelayTests.cs | 403 +++++++++---------
7 files changed, 531 insertions(+), 554 deletions(-)
create mode 100644 .backlog/tasks/task-17 - Consolidate-duplicate-Facts-into-Theories.md
diff --git a/.backlog/tasks/task-17 - Consolidate-duplicate-Facts-into-Theories.md b/.backlog/tasks/task-17 - Consolidate-duplicate-Facts-into-Theories.md
new file mode 100644
index 00000000..0358623b
--- /dev/null
+++ b/.backlog/tasks/task-17 - Consolidate-duplicate-Facts-into-Theories.md
@@ -0,0 +1,19 @@
+---
+id: TASK-17
+title: Consolidate duplicate Facts into Theories
+status: Done
+assignee:
+ - claude
+ - piotrzajac
+created_date: '2026-04-21 08:21'
+updated_date: '2026-04-21 11:06'
+labels: []
+dependencies: []
+priority: low
+---
+
+## Acceptance Criteria
+
+- [x] #1 Identify all [Fact] methods across the all test projects that test the same behavior with different inputs
+- [x] #2 Replace duplicate Facts with a single [Theory] using [InlineData] or [MemberData]/[TheoryData] as appropriate
+
diff --git a/dotnet-tools.json b/dotnet-tools.json
index 5ead7f07..cda38d40 100644
--- a/dotnet-tools.json
+++ b/dotnet-tools.json
@@ -17,7 +17,7 @@
"rollForward": true
},
"dotnet-stryker": {
- "version": "4.14.0",
+ "version": "4.14.1",
"commands": [
"dotnet-stryker"
],
diff --git a/src/Objectivity.AutoFixture.XUnit2.Core.Tests/Common/EnumerableExtensionsTests.cs b/src/Objectivity.AutoFixture.XUnit2.Core.Tests/Common/EnumerableExtensionsTests.cs
index 625eb51f..d3bd151e 100644
--- a/src/Objectivity.AutoFixture.XUnit2.Core.Tests/Common/EnumerableExtensionsTests.cs
+++ b/src/Objectivity.AutoFixture.XUnit2.Core.Tests/Common/EnumerableExtensionsTests.cs
@@ -1,121 +1,114 @@
-namespace Objectivity.AutoFixture.XUnit2.Core.Tests.Common
-{
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.Diagnostics.CodeAnalysis;
-
- using global::AutoFixture.Xunit2;
-
- using Objectivity.AutoFixture.XUnit2.Core.Common;
-
- using Xunit;
-
- [Collection("EnumerableExtensions")]
- [Trait("Category", "Common")]
- public class EnumerableExtensionsTests
- {
- [Fact(DisplayName = "GIVEN uninitialized argument WHEN TryGetEnumerableSingleTypeArgument is invoked THEN exception is thrown")]
- [SuppressMessage("ReSharper", "UnusedVariable", Justification = "This is good enougth to test the logic.")]
- public void GivenUninitializedArgument_WhenTryGetEnumerableSingleTypeArgumentIsInvoked_ThenExceptionIsThrown()
- {
- // Arrange
- Type enumerableType = null;
-
- // Act
- object Act() => enumerableType.TryGetEnumerableSingleTypeArgument(out _);
-
- // Assert
- var exception = Assert.Throws(Act);
- Assert.Equal("type", exception.ParamName);
- }
-
- [InlineData(typeof(int[]), typeof(int))]
- [InlineData(typeof(List), typeof(int))]
- [InlineData(typeof(Dictionary), typeof(KeyValuePair))]
- [InlineData(typeof(IEnumerable), typeof(int))]
- [Theory(DisplayName = "GIVEN valid collection WHEN TryGetEnumerableSingleTypeArgument is invoked THEN collection single type argument returned")]
- public void GivenValidCollection_WhenTryGetEnumerableSingleTypeArgumentIsInvoked_ThenCollectionSingleTypeArgumentReturned(Type enumerableType, Type expectedType)
- {
- // Arrange
- // Act
- var isSuccessful = enumerableType.TryGetEnumerableSingleTypeArgument(out var itemType);
-
- // Assert
- Assert.True(isSuccessful);
- Assert.Equal(expectedType, itemType);
- }
-
- [InlineData(typeof(Tuple))]
- [InlineData(typeof(IEnumerable))]
- [Theory(DisplayName = "GIVEN invalid collection WHEN TryGetEnumerableSingleTypeArgument is invoked THEN no argument returned")]
- public void GivenInvalidCollection_WhenTryGetEnumerableSingleTypeArgumentIsInvoked_ThenNoArgumentReturned(Type enumerableType)
- {
- // Arrange
- // Act
- var isSuccessful = enumerableType.TryGetEnumerableSingleTypeArgument(out _);
-
- // Assert
- Assert.False(isSuccessful);
- }
-
- [Fact(DisplayName = "GIVEN generic definition collection WHEN TryGetEnumerableSingleTypeArgument is invoked THEN no argument returned")]
- public void GivenGenericDefinitionCollection_WhenTryGetEnumerableSingleTypeArgumentIsInvoked_ThenNoArgumentReturned()
- {
- // Arrange
- var enumerableType = typeof(IEnumerable).GetGenericTypeDefinition();
-
- // Act
- var isSuccessful = enumerableType.TryGetEnumerableSingleTypeArgument(out _);
-
- // Assert
- Assert.False(isSuccessful);
- }
-
- [InlineData(null, typeof(int), "items")]
- [InlineData(new[] { 1 }, null, "itemType")]
- [Theory(DisplayName = "GIVEN uninitialized argument WHEN ToTypedArray is invoked THEN exception is thrown")]
- public void GivenUninitializedArgument_WhenToTypedArrayIsInvoked_ThenExceptionIsThrown(
- IEnumerable items,
- Type itemType,
- string exceptionParamName)
- {
- // Arrange
- // Act
- object Act() => items.ToTypedArray(itemType);
-
- // Assert
- var exception = Assert.Throws(Act);
- Assert.Equal(exceptionParamName, exception.ParamName);
- }
-
- [AutoData]
- [Theory(DisplayName = "GIVEN typed enumerable WHEN ToTypedArray is invoked THEN array is returned")]
- public void GivenTypedEnumerable_WhenToTypedArrayIsInvoked_ThenArrayIsReturned(int[] items)
- {
- // Arrange
- var itemType = typeof(int);
-
- // Act
- var array = items.ToTypedArray(itemType);
-
- // Assert
- Assert.Equal(items, array);
- Assert.True(array.GetType().IsArray);
- }
-
- [AutoData]
- [Theory(DisplayName = "GIVEN enumerable WHEN ToTypedArray is invoked THEN array is returned")]
- public void GivenEnumerable_WhenToTypedArrayIsInvoked_ThenArrayIsReturned(BitArray items)
- {
- // Arrange
- var itemType = typeof(bool);
-
- // Act
- var array = items.ToTypedArray(itemType);
-
- // Assert
- Assert.Equal(items, array);
- }
- }
-}
+namespace Objectivity.AutoFixture.XUnit2.Core.Tests.Common
+{
+ using System;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Diagnostics.CodeAnalysis;
+
+ using global::AutoFixture.Xunit2;
+
+ using Objectivity.AutoFixture.XUnit2.Core.Common;
+
+ using Xunit;
+
+ [Collection("EnumerableExtensions")]
+ [Trait("Category", "Common")]
+ public class EnumerableExtensionsTests
+ {
+ public static TheoryData InvalidCollectionTestData { get; } = new()
+ {
+ typeof(Tuple),
+ typeof(IEnumerable),
+ typeof(IEnumerable).GetGenericTypeDefinition(),
+ };
+
+ [Fact(DisplayName = "GIVEN uninitialized argument WHEN TryGetEnumerableSingleTypeArgument is invoked THEN exception is thrown")]
+ [SuppressMessage("ReSharper", "UnusedVariable", Justification = "This is good enougth to test the logic.")]
+ public void GivenUninitializedArgument_WhenTryGetEnumerableSingleTypeArgumentIsInvoked_ThenExceptionIsThrown()
+ {
+ // Arrange
+ Type enumerableType = null;
+
+ // Act
+ object Act() => enumerableType.TryGetEnumerableSingleTypeArgument(out _);
+
+ // Assert
+ var exception = Assert.Throws(Act);
+ Assert.Equal("type", exception.ParamName);
+ }
+
+ [InlineData(typeof(int[]), typeof(int))]
+ [InlineData(typeof(List), typeof(int))]
+ [InlineData(typeof(Dictionary), typeof(KeyValuePair))]
+ [InlineData(typeof(IEnumerable), typeof(int))]
+ [Theory(DisplayName = "GIVEN valid collection WHEN TryGetEnumerableSingleTypeArgument is invoked THEN collection single type argument returned")]
+ public void GivenValidCollection_WhenTryGetEnumerableSingleTypeArgumentIsInvoked_ThenCollectionSingleTypeArgumentReturned(Type enumerableType, Type expectedType)
+ {
+ // Arrange
+ // Act
+ var isSuccessful = enumerableType.TryGetEnumerableSingleTypeArgument(out var itemType);
+
+ // Assert
+ Assert.True(isSuccessful);
+ Assert.Equal(expectedType, itemType);
+ }
+
+ [MemberData(nameof(InvalidCollectionTestData))]
+ [Theory(DisplayName = "GIVEN invalid collection WHEN TryGetEnumerableSingleTypeArgument is invoked THEN no argument returned")]
+ public void GivenInvalidCollection_WhenTryGetEnumerableSingleTypeArgumentIsInvoked_ThenNoArgumentReturned(Type enumerableType)
+ {
+ // Arrange
+ // Act
+ var isSuccessful = enumerableType.TryGetEnumerableSingleTypeArgument(out _);
+
+ // Assert
+ Assert.False(isSuccessful);
+ }
+
+ [InlineData(null, typeof(int), "items")]
+ [InlineData(new[] { 1 }, null, "itemType")]
+ [Theory(DisplayName = "GIVEN uninitialized argument WHEN ToTypedArray is invoked THEN exception is thrown")]
+ public void GivenUninitializedArgument_WhenToTypedArrayIsInvoked_ThenExceptionIsThrown(
+ IEnumerable items,
+ Type itemType,
+ string exceptionParamName)
+ {
+ // Arrange
+ // Act
+ object Act() => items.ToTypedArray(itemType);
+
+ // Assert
+ var exception = Assert.Throws(Act);
+ Assert.Equal(exceptionParamName, exception.ParamName);
+ }
+
+ [AutoData]
+ [Theory(DisplayName = "GIVEN typed enumerable WHEN ToTypedArray is invoked THEN array is returned")]
+ public void GivenTypedEnumerable_WhenToTypedArrayIsInvoked_ThenArrayIsReturned(int[] items)
+ {
+ // Arrange
+ var itemType = typeof(int);
+
+ // Act
+ var array = items.ToTypedArray(itemType);
+
+ // Assert
+ Assert.Equal(items, array);
+ Assert.True(array.GetType().IsArray);
+ }
+
+ [AutoData]
+ [Theory(DisplayName = "GIVEN enumerable WHEN ToTypedArray is invoked THEN array is returned")]
+ public void GivenEnumerable_WhenToTypedArrayIsInvoked_ThenArrayIsReturned(BitArray items)
+ {
+ // Arrange
+ var itemType = typeof(bool);
+
+ // Act
+ var array = items.ToTypedArray(itemType);
+
+ // Assert
+ Assert.Equal(items, array);
+ }
+ }
+}
diff --git a/src/Objectivity.AutoFixture.XUnit2.Core.Tests/Requests/ValuesRequestTests.cs b/src/Objectivity.AutoFixture.XUnit2.Core.Tests/Requests/ValuesRequestTests.cs
index 0f1b75c3..76e60ae6 100644
--- a/src/Objectivity.AutoFixture.XUnit2.Core.Tests/Requests/ValuesRequestTests.cs
+++ b/src/Objectivity.AutoFixture.XUnit2.Core.Tests/Requests/ValuesRequestTests.cs
@@ -14,6 +14,12 @@
[Trait("Category", "Requests")]
public class ValuesRequestTests
{
+ public static TheoryData NullArgumentConstructorTestData { get; } = new()
+ {
+ { null, null, "operandType" },
+ { typeof(int), null, "values" },
+ };
+
public static TheoryData ComparisonTestData { get; } = new()
{
{ typeof(int), new[] { 1 }, typeof(int), new[] { 1 }, true },
@@ -24,34 +30,18 @@ public class ValuesRequestTests
{ typeof(int), new[] { 1, 2 }, typeof(int), new[] { 2 }, false },
};
- [Fact(DisplayName = "GIVEN uninitialized type argument WHEN constructor is invoked THEN exception is thrown")]
- public void GivenUninitializedTypeArgument_WhenConstructorIsInvoked_ThenExceptionIsThrown()
+ [MemberData(nameof(NullArgumentConstructorTestData))]
+ [Theory(DisplayName = "GIVEN uninitialized argument WHEN constructor is invoked THEN exception is thrown")]
+ public void GivenUninitializedArgument_WhenConstructorIsInvoked_ThenExceptionIsThrown(
+ Type type, object[] values, string expectedParamName)
{
// Arrange
- Type type = null;
- object[] values = null;
-
- // Act
- object Act() => new FixedValuesRequest(type, values);
-
- // Assert
- var exception = Assert.Throws(Act);
- Assert.Equal("operandType", exception.ParamName);
- }
-
- [Fact(DisplayName = "GIVEN uninitialized values argument WHEN constructor is invoked THEN exception is thrown")]
- public void GivenUninitializedValuesArgument_WhenConstructorIsInvoked_ThenExceptionIsThrown()
- {
- // Arrange
- var type = typeof(int);
- object[] values = null;
-
// Act
object Act() => new FixedValuesRequest(type, values);
// Assert
var exception = Assert.Throws(Act);
- Assert.Equal("values", exception.ParamName);
+ Assert.Equal(expectedParamName, exception.ParamName);
}
[Fact(DisplayName = "GIVEN empty values argument WHEN constructor is invoked THEN exception is thrown")]
diff --git a/src/Objectivity.AutoFixture.XUnit2.Core.Tests/SpecimenBuilders/RandomExceptValuesGeneratorTests.cs b/src/Objectivity.AutoFixture.XUnit2.Core.Tests/SpecimenBuilders/RandomExceptValuesGeneratorTests.cs
index 49c87b90..bbb85c24 100644
--- a/src/Objectivity.AutoFixture.XUnit2.Core.Tests/SpecimenBuilders/RandomExceptValuesGeneratorTests.cs
+++ b/src/Objectivity.AutoFixture.XUnit2.Core.Tests/SpecimenBuilders/RandomExceptValuesGeneratorTests.cs
@@ -1,83 +1,75 @@
-namespace Objectivity.AutoFixture.XUnit2.Core.Tests.SpecimenBuilders
-{
- using System;
-
- using global::AutoFixture;
- using global::AutoFixture.Kernel;
-
- using Moq;
-
- using Objectivity.AutoFixture.XUnit2.Core.Requests;
- using Objectivity.AutoFixture.XUnit2.Core.SpecimenBuilders;
-
- using Xunit;
-
- [Collection("RandomExceptValuesGenerator")]
- [Trait("Category", "SpecimenBuilders")]
- public class RandomExceptValuesGeneratorTests
- {
- [Fact(DisplayName = "GIVEN uninitialized context WHEN Create is invoked THEN exception is thrown")]
- public void GivenUninitializedContext_WhenCreateIsInvoked_ThenExceptionIsThrown()
- {
- // Arrange
- var builder = new RandomExceptValuesGenerator();
-
- // Act
- object Act() => builder.Create(new object(), null);
-
- // Assert
- var exception = Assert.Throws(Act);
- Assert.Equal("context", exception.ParamName);
- }
-
- [Fact(DisplayName = "GIVEN uninitialized request WHEN Create is invoked THEN exception is thrown")]
- public void GivenUninitializedRequest_WhenCreateIsInvoked_ThenExceptionIsThrown()
- {
- // Arrange
- var builder = new RandomExceptValuesGenerator();
- var context = new Mock();
-
- // Act
- object Act() => builder.Create(null, context.Object);
-
- // Assert
- var exception = Assert.Throws(Act);
- Assert.Equal("request", exception.ParamName);
- }
-
- [Fact(DisplayName = "GIVEN excluded value and context which resolves to the same value WHEN Create is invoked THEN exception is thrown")]
- public void GivenExcludedValueAndContextWhichResolvesToTheSameValue_WhenCreateIsInvoked_ThenExceptionIsThrown()
- {
- // Arrange
- var builder = new RandomExceptValuesGenerator();
- var context = new Mock();
- const int duplicateValue = 5;
- context.Setup(x => x.Resolve(It.IsNotNull