Skip to content

Commit 313306b

Browse files
authored
Merge pull request #55 from siewers/main
Support CombinatorialMemberData for IEnumerable<string>
2 parents cee1567 + 6ed590e commit 313306b

File tree

2 files changed

+45
-14
lines changed

2 files changed

+45
-14
lines changed

src/Xunit.Combinatorial/CombinatorialMemberDataAttribute.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -204,22 +204,22 @@ private bool ParameterTypesCompatible(ParameterInfo[] parameters, object?[]? arg
204204
/// <exception cref="ArgumentException">Throw when <paramref name="enumerableType"/> does not conform to requirements or does not produce values assignable to <paramref name="parameterInfo"/>.</exception>
205205
private void EnsureValidMemberDataType(Type enumerableType, Type declaringType, ParameterInfo parameterInfo)
206206
{
207-
TypeInfo enumerableTypeInfo = typeof(IEnumerable).GetTypeInfo();
208-
if (!enumerableTypeInfo.IsAssignableFrom(enumerableType.GetTypeInfo()))
209-
{
210-
throw new ArgumentException($"Member {this.MemberName} on {declaringType.FullName} must return a type that implements {typeof(IEnumerable)}.");
211-
}
212-
213207
TypeInfo? enumeratedType = GetEnumeratedType(enumerableType);
214208
if (enumeratedType is null)
215209
{
216210
throw new ArgumentException($"Member {this.MemberName} on {declaringType.FullName} must return a type that implements IEnumerable<T>.");
217211
}
218212

219-
if (enumerableTypeInfo.IsAssignableFrom(enumeratedType))
213+
if (enumeratedType.IsArray)
214+
{
215+
throw new ArgumentException(
216+
$"Member {this.MemberName} on {declaringType.FullName} returned an IEnumerable<{enumeratedType.Name}>, which is not supported.");
217+
}
218+
219+
if (enumeratedType.IsGenericType && enumeratedType.GetGenericTypeDefinition() == typeof(IEnumerable<>))
220220
{
221221
throw new ArgumentException(
222-
$"Member {this.MemberName} on {declaringType.FullName} returned an IEnumerable<object[]>, which is not supported.");
222+
$"Member {this.MemberName} on {declaringType.FullName} returned an IEnumerable<IEnumerable<{enumeratedType.GetGenericArguments()[0].Name}>>, which is not supported.");
223223
}
224224

225225
if (!enumeratedType.IsAssignableFrom(parameterInfo.ParameterType.GetTypeInfo()))

test/Xunit.Combinatorial.Tests/CombinatorialMemberDataAttributeTests.cs

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ public class CombinatorialMemberDataAttributeTests
99
{
1010
private static readonly MethodInfo StubIntMethodInfo = typeof(CombinatorialMemberDataAttributeTests).GetMethod(nameof(StubIntMethod), BindingFlags.Instance | BindingFlags.NonPublic)!;
1111
private static readonly MethodInfo StubGuidMethodInfo = typeof(CombinatorialMemberDataAttributeTests).GetMethod(nameof(StubGuidMethod), BindingFlags.Instance | BindingFlags.NonPublic)!;
12+
private static readonly MethodInfo StubStringMethodInfo = typeof(CombinatorialMemberDataAttributeTests).GetMethod(nameof(StubStringMethod), BindingFlags.Instance | BindingFlags.NonPublic)!;
1213

1314
[Fact]
1415
public void EnumerableOfIntReturnsValues()
@@ -44,17 +45,17 @@ public void EnumerableOfArrayThrows()
4445
ParameterInfo parameter = StubIntMethodInfo.GetParameters()[0];
4546

4647
ArgumentException? exception = Assert.Throws<ArgumentException>(() => attribute.GetValues(parameter));
47-
Assert.Equal($"Member {nameof(GetValuesAsEnumerableOfIntArray)} on {nameof(CombinatorialMemberDataAttributeTests)} returned an IEnumerable<object[]>, which is not supported.", exception.Message);
48+
Assert.Equal($"Member {nameof(GetValuesAsEnumerableOfIntArray)} on {nameof(CombinatorialMemberDataAttributeTests)} returned an IEnumerable<Int32[]>, which is not supported.", exception.Message);
4849
}
4950

5051
[Fact]
51-
public void NonEnumerableThrows()
52+
public void EnumerableOfEnumerableThrows()
5253
{
53-
var attribute = new CombinatorialMemberDataAttribute(nameof(GetValuesAsDoesNotImplementIEnumerable));
54+
var attribute = new CombinatorialMemberDataAttribute(nameof(GetValuesAsEnumerableOfIntEnumerable));
5455
ParameterInfo parameter = StubIntMethodInfo.GetParameters()[0];
5556

5657
ArgumentException? exception = Assert.Throws<ArgumentException>(() => attribute.GetValues(parameter));
57-
Assert.Equal($"Member {nameof(GetValuesAsDoesNotImplementIEnumerable)} on {typeof(CombinatorialMemberDataAttributeTests)} must return a type that implements System.Collections.IEnumerable.", exception.Message);
58+
Assert.Equal($"Member {nameof(GetValuesAsEnumerableOfIntEnumerable)} on {nameof(CombinatorialMemberDataAttributeTests)} returned an IEnumerable<IEnumerable<Int32>>, which is not supported.", exception.Message);
5859
}
5960

6061
[Fact]
@@ -78,6 +79,16 @@ public void EnumerableOfGuidReturnsValue()
7879
Assert.Contains(values, obj => obj is Guid guid && guid != Guid.Empty);
7980
}
8081

82+
[Fact]
83+
public void EnumerableOfStringReturnsValue()
84+
{
85+
var attribute = new CombinatorialMemberDataAttribute(nameof(GetValuesAsEnumerableOfString));
86+
ParameterInfo parameter = StubStringMethodInfo.GetParameters()[0];
87+
object?[]? values = attribute.GetValues(parameter);
88+
89+
Assert.Contains(values, obj => obj is string str && !string.IsNullOrEmpty(str));
90+
}
91+
8192
[Fact]
8293
public void IncompatibleMemberDataTypeThrows()
8394
{
@@ -100,8 +111,6 @@ private static IEnumerable<int> GetValuesAsEnumerableOfInt()
100111

101112
private static ListOfInt GetValuesAsConcreteNonGenericClassImplementingEnumerableOfInt() => new ListOfInt { 1, 2, 3, 4 };
102113

103-
private static DoesNotImplementIEnumerable GetValuesAsDoesNotImplementIEnumerable() => new();
104-
105114
private static ImplementsOnlyNonGenericIEnumerable GetValuesAsTypeThatImplementsNonGenericIEnumerable() => new();
106115

107116
private static IEnumerable<int[]> GetValuesAsEnumerableOfIntArray()
@@ -113,6 +122,15 @@ private static IEnumerable<int[]> GetValuesAsEnumerableOfIntArray()
113122
yield return new[] { 5 };
114123
}
115124

125+
private static IEnumerable<IEnumerable<int>> GetValuesAsEnumerableOfIntEnumerable()
126+
{
127+
yield return new[] { 1 };
128+
yield return new[] { 2 };
129+
yield return new[] { 3 };
130+
yield return new[] { 4 };
131+
yield return new[] { 5 };
132+
}
133+
116134
private static IEnumerable<Guid> GetValuesAsEnumerableOfGuid()
117135
{
118136
yield return Guid.NewGuid();
@@ -122,6 +140,15 @@ private static IEnumerable<Guid> GetValuesAsEnumerableOfGuid()
122140
yield return Guid.NewGuid();
123141
}
124142

143+
private static IEnumerable<string> GetValuesAsEnumerableOfString()
144+
{
145+
yield return Guid.NewGuid().ToString();
146+
yield return Guid.NewGuid().ToString();
147+
yield return Guid.NewGuid().ToString();
148+
yield return Guid.NewGuid().ToString();
149+
yield return Guid.NewGuid().ToString();
150+
}
151+
125152
private void StubIntMethod(int p1)
126153
{
127154
}
@@ -130,6 +157,10 @@ private void StubGuidMethod(Guid p1)
130157
{
131158
}
132159

160+
private void StubStringMethod(string p1)
161+
{
162+
}
163+
133164
private class ListOfInt : List<int>
134165
{
135166
}

0 commit comments

Comments
 (0)