Skip to content

Commit 540cdbb

Browse files
authored
Merge pull request #125 from feO2x/issue-119-must-contain-for-immutable-array
MustContain for immutable array
2 parents 8e46099 + e11e6a2 commit 540cdbb

File tree

3 files changed

+137
-1
lines changed

3 files changed

+137
-1
lines changed

Code/Light.GuardClauses.Tests/CollectionAssertions/MustContainTests.cs

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
using System;
1+
using System;
22
using System.Collections.Generic;
3+
using System.Collections.Immutable;
34
using System.Collections.ObjectModel;
45
using FluentAssertions;
56
using Light.GuardClauses.Exceptions;
@@ -69,4 +70,72 @@ public static void CallerArgumentExpression()
6970
act.Should().Throw<MissingItemException>()
7071
.WithParameterName(nameof(array));
7172
}
73+
74+
[Theory]
75+
[InlineData(new[] { 1, 2, 3 }, 5)]
76+
[InlineData(new[] { -5491, 6199 }, 42)]
77+
public static void ImmutableArrayItemNotPartOf(int[] source, int item)
78+
{
79+
var immutableArray = source.ToImmutableArray();
80+
Action act = () => immutableArray.MustContain(item, nameof(immutableArray));
81+
82+
var assertion = act.Should().Throw<MissingItemException>().Which;
83+
assertion.Message.Should().Contain($"{nameof(immutableArray)} must contain {item}, but it actually does not.");
84+
}
85+
86+
[Theory]
87+
[InlineData(new[] { "Foo", "Bar" }, "Foo")]
88+
[InlineData(new[] { "Foo", "Bar", "Foo" }, "Foo")]
89+
[InlineData(new[] { "Qux" }, "Qux")]
90+
[InlineData(new[] { "Qux", null }, null)]
91+
public static void ImmutableArrayItemPartOf(string[] source, string item)
92+
{
93+
var immutableArray = source.ToImmutableArray();
94+
immutableArray.MustContain(item).Should().Equal(immutableArray);
95+
}
96+
97+
[Fact]
98+
public static void ImmutableArrayEmptyDoesNotContainItem()
99+
{
100+
var immutableArray = ImmutableArray<string>.Empty;
101+
Action act = () => immutableArray.MustContain("Foo");
102+
103+
act.Should().Throw<MissingItemException>();
104+
}
105+
106+
[Theory]
107+
[InlineData(new[] { 42L, 100L }, 1337L)]
108+
public static void ImmutableArrayCustomException(long[] source, long item)
109+
{
110+
var immutableArray = source.ToImmutableArray();
111+
Test.CustomException(
112+
immutableArray,
113+
item,
114+
(array, i, exceptionFactory) => array.MustContain(i, exceptionFactory)
115+
);
116+
}
117+
118+
[Fact]
119+
public static void ImmutableArrayCustomExceptionNotThrown()
120+
{
121+
var immutableArray = ImmutableArray.Create(1, 2, 3);
122+
immutableArray.MustContain(2, (_, _) => new Exception()).Should().Equal(immutableArray);
123+
}
124+
125+
[Fact]
126+
public static void ImmutableArrayCustomMessage() =>
127+
Test.CustomMessage<MissingItemException>(
128+
message => ImmutableArray<string>.Empty.MustContain("Foo", message: message)
129+
);
130+
131+
[Fact]
132+
public static void ImmutableArrayCallerArgumentExpression()
133+
{
134+
var immutableArray = ImmutableArray.Create("Foo", "Bar");
135+
136+
var act = () => immutableArray.MustContain("Baz");
137+
138+
act.Should().Throw<MissingItemException>()
139+
.WithParameterName(nameof(immutableArray));
140+
}
72141
}

Code/Light.GuardClauses/Check.MustContain.cs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Collections.Immutable;
34
using System.Linq;
45
using System.Runtime.CompilerServices;
56
using JetBrains.Annotations;
@@ -197,4 +198,50 @@ public static string MustContain(
197198

198199
return parameter;
199200
}
201+
202+
/// <summary>
203+
/// Ensures that the immutable array contains the specified item, or otherwise throws a <see cref="MissingItemException" />.
204+
/// </summary>
205+
/// <param name="parameter">The immutable array to be checked.</param>
206+
/// <param name="item">The item that must be part of the immutable array.</param>
207+
/// <param name="parameterName">The name of the parameter (optional).</param>
208+
/// <param name="message">The message that will be passed to the resulting exception (optional).</param>
209+
/// <exception cref="MissingItemException">Thrown when <paramref name="parameter" /> does not contain <paramref name="item" />.</exception>
210+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
211+
public static ImmutableArray<T> MustContain<T>(
212+
this ImmutableArray<T> parameter,
213+
T item,
214+
[CallerArgumentExpression("parameter")] string? parameterName = null,
215+
string? message = null
216+
)
217+
{
218+
if (!parameter.Contains(item))
219+
{
220+
Throw.MissingItem(parameter, item, parameterName, message);
221+
}
222+
223+
return parameter;
224+
}
225+
226+
/// <summary>
227+
/// Ensures that the immutable array contains the specified item, or otherwise throws your custom exception.
228+
/// </summary>
229+
/// <param name="parameter">The immutable array to be checked.</param>
230+
/// <param name="item">The item that must be part of the immutable array.</param>
231+
/// <param name="exceptionFactory">The delegate that creates your custom exception. <paramref name="parameter" /> and <paramref name="item" /> are passed to this delegate.</param>
232+
/// <exception cref="Exception">Your custom exception thrown when <paramref name="parameter" /> does not contain <paramref name="item" />.</exception>
233+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
234+
public static ImmutableArray<T> MustContain<T>(
235+
this ImmutableArray<T> parameter,
236+
T item,
237+
Func<ImmutableArray<T>, T, Exception> exceptionFactory
238+
)
239+
{
240+
if (!parameter.Contains(item))
241+
{
242+
Throw.CustomException(exceptionFactory, parameter, item);
243+
}
244+
245+
return parameter;
246+
}
200247
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Issue 119 - MustContain for ImmutableArray
2+
3+
## Context
4+
5+
The .NET library Light.GuardClauses already has several assertions for collections. They often rely on `IEnumerable<T>` or `IEnumerable`. However, these assertions would result in `ImmutableArray<T>` being boxed - we want to avoid that by providing dedicated assertions for this type which avoids boxing. For this issue, we implement the `MustContain` assertion for `ImmutableArray<T>`.
6+
7+
## Tasks for this issue
8+
9+
- [ ] The production code should be placed in the Light.GuardClauses project. Extend the existing `Check.MustContain.cs` in the root folder of the project.
10+
- [ ] In this file, add several extension method overloads called `MustContain` for `ImmutableArray<T>`. They should be placed in the existing class `Check` which is marked as `partial`.
11+
- [ ] Each assertion in Light.GuardClauses has two overloads - the first one takes the optional `parameterName` and `message` arguments and throws the default exception (in this case the existing `MissingItemException`). The actual exception is thrown in the `Throw` class, you need to call the existing method for it in this class.
12+
- [ ] The other overload takes a delegate which allows the caller to provide their own custom exceptions. Use the existing `Throw.CustomException` method and pass the delegate, the erroneous `ImmutableArray<T>` instance and the missing item.
13+
- [ ] Create unit tests for both overloads. The corresponding tests should be placed in Light.GuardClauses.Tests project, in the existing file 'CollectionAssertions/MustContainTests.cs'. Please follow conventions of the existing tests (e.g. use FluentAssertions' `Should()` for assertions).
14+
15+
## Notes
16+
17+
- There are already plenty of other assertions and tests in this library. All overloads are placed in the same file in the production code project. The test projects has top-level folders for different groups of assertions, like `CollectionAssertions`, `StringAssertions`, `DateTimeAssertions` and so on. Please take a look at them to follow a similar structure and code style.
18+
- This assertion specifically targets `ImmutableArray<T>` to avoid boxing that would occur with generic `IEnumerable<T>` extensions.
19+
- The assertion should verify that the `ImmutableArray<T>` contains the specified item.
20+
- If you have any questions or suggestions, please ask me about them.

0 commit comments

Comments
 (0)