Skip to content

Commit 4b23520

Browse files
authored
String assertions (#16)
* Add assertions for string * Add ignoreCase * Bump .NET to 5.0.100-rc.1
1 parent cc8c49a commit 4b23520

31 files changed

+432
-102
lines changed

.github/workflows/dotnetcore.yml

+6-6
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@ jobs:
1616
- name: Setup .NET Core
1717
uses: actions/setup-dotnet@v1.4.0
1818
with:
19-
dotnet-version: 3.1.102
19+
dotnet-version: 5.0.100-rc.1
2020
- name: Build solution
2121
run: dotnet build -c:Release
2222
- name: Tests
23-
run: dotnet test ./NetFabric.Assertive.UnitTests/NetFabric.Assertive.UnitTests.csproj -f:netcoreapp3.1 -c:Release
23+
run: dotnet test ./NetFabric.Assertive.UnitTests/NetFabric.Assertive.UnitTests.csproj -f:net5.0 -c:Release
2424

2525
windows:
2626
runs-on: windows-latest
@@ -30,15 +30,15 @@ jobs:
3030
- name: Setup .NET Core
3131
uses: actions/setup-dotnet@v1.4.0
3232
with:
33-
dotnet-version: 3.1.102
33+
dotnet-version: 5.0.100-rc.1
3434
- name: Build with dotnet
3535
run: dotnet build -c:Release
3636
- name: Tests
37-
run: dotnet test ./NetFabric.Assertive.UnitTests/NetFabric.Assertive.UnitTests.csproj -c:Release
37+
run: dotnet test ./NetFabric.Assertive.UnitTests/NetFabric.Assertive.UnitTests.csproj -c:Release -f:net5.0
3838
- name: Generate coverage report
39-
run: dotnet test ./NetFabric.Assertive.UnitTests/NetFabric.Assertive.UnitTests.csproj -c:Release -f:netcoreapp3.1 -p:CollectCoverage=true -p:CoverletOutputFormat=lcov -p:CoverletOutput=TestResults/
39+
run: dotnet test ./NetFabric.Assertive.UnitTests/NetFabric.Assertive.UnitTests.csproj -c:Release -f:net5.0 -p:CollectCoverage=true -p:CoverletOutputFormat=lcov -p:CoverletOutput=TestResults/
4040
- name: Publish coverage report to coveralls.io
4141
uses: coverallsapp/github-action@master
4242
with:
4343
github-token: ${{ secrets.GITHUB_TOKEN }}
44-
path-to-lcov: ./NetFabric.Assertive.UnitTests/TestResults/coverage.netcoreapp3.1.info
44+
path-to-lcov: ./NetFabric.Assertive.UnitTests/TestResults/coverage.net5.0.info

Directory.Build.props

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<PropertyGroup>
44
<Authors>Antao Almada</Authors>
55
<Copyright>Copyright 2019-2020 Antao Almada</Copyright>
6-
<LangVersion>8.0</LangVersion>
6+
<LangVersion>9.0</LangVersion>
77
<Features>strict</Features>
88
</PropertyGroup>
99

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
using System;
2+
using Xunit;
3+
4+
namespace NetFabric.Assertive.UnitTests
5+
{
6+
public partial class StringAssertionsTests
7+
{
8+
[Theory]
9+
[InlineData(null, null, false)]
10+
[InlineData("", "", false)]
11+
[InlineData("", "", true)]
12+
[InlineData(" ", " ", false)]
13+
[InlineData(" ", " ", true)]
14+
[InlineData("a", "a", false)]
15+
[InlineData("a", "a", true)]
16+
[InlineData("a", "A", true)]
17+
public void BeEqualTo_With_Equal_Should_NotThrow(string value, string expected, bool ignoreCase)
18+
{
19+
// Arrange
20+
21+
// Act
22+
_ = value.Must().BeEqualTo(expected, ignoreCase);
23+
24+
// Assert
25+
}
26+
27+
public static TheoryData<string, string, string> Enumerable_NotEqualNullData =>
28+
new TheoryData<string, string, string>
29+
{
30+
{ null, "", $"Expected to be equal but it's not.{Environment.NewLine}Expected: <empty>{Environment.NewLine}Actual: <null>" },
31+
{ "", null, $"Expected to be equal but it's not.{Environment.NewLine}Expected: <null>{Environment.NewLine}Actual: <empty>" },
32+
};
33+
34+
[Theory]
35+
[MemberData(nameof(Enumerable_NotEqualNullData))]
36+
public void BeEqualTo_With_NotEqual_Null_Should_Throw(string actual, string expected, string message)
37+
{
38+
// Arrange
39+
40+
// Act
41+
void action() => actual.Must().BeEqualTo(expected);
42+
43+
// Assert
44+
var exception = Assert.Throws<EqualToAssertionException<string, string>>(action);
45+
Assert.Equal(actual, exception.Actual);
46+
Assert.Equal(expected, exception.Expected);
47+
Assert.Equal(message, exception.Message);
48+
}
49+
50+
51+
public static TheoryData<string, string, int, string> Enumerable_NotEqualData =>
52+
new TheoryData<string, string, int, string>
53+
{
54+
{ "*", "", 0, $"Expected to be equal but it's not at position 0.{Environment.NewLine}Expected: <empty>{Environment.NewLine} Actual: *{Environment.NewLine} \u25b2" },
55+
{ "*", "0", 0, $"Expected to be equal but it's not at position 0.{Environment.NewLine}Expected: 0{Environment.NewLine} Actual: *{Environment.NewLine} \u25b2" },
56+
{ "0", "012345", 1, $"Expected to be equal but it's not at position 1.{Environment.NewLine}Expected: 012345{Environment.NewLine} Actual: 0{Environment.NewLine} \u25b2" },
57+
{ "012345", "0", 1, $"Expected to be equal but it's not at position 1.{Environment.NewLine}Expected: 0{Environment.NewLine} Actual: 012345{Environment.NewLine} \u25b2" },
58+
{ "01234*", "012345", 5, $"Expected to be equal but it's not at position 5.{Environment.NewLine}Expected: 012345{Environment.NewLine} Actual: 01234*{Environment.NewLine} \u25b2" },
59+
{ "01234*6789", "0123456789", 5, $"Expected to be equal but it's not at position 5.{Environment.NewLine}Expected: 0123456789{Environment.NewLine} Actual: 01234*6789{Environment.NewLine} \u25b2" },
60+
{ "0123456789a*", "0123456789ab", 11, $"Expected to be equal but it's not at position 11.{Environment.NewLine}Expected: \u2026123456789ab{Environment.NewLine} Actual: \u2026123456789a*{Environment.NewLine} \u25b2" },
61+
{ "0123456789a*cdefghijkl", "0123456789abcdefghijkl", 11, $"Expected to be equal but it's not at position 11.{Environment.NewLine}Expected: \u2026123456789abcdefghijk\u2026{Environment.NewLine} Actual: \u2026123456789a*cdefghijk\u2026{Environment.NewLine} \u25b2" },
62+
{ " \n\r34*", " \n\r345", 5, $"Expected to be equal but it's not at position 5.{Environment.NewLine}Expected: \u2022\u2193\u2190345{Environment.NewLine} Actual: \u2022\u2193\u219034*{Environment.NewLine} \u25b2" },
63+
};
64+
65+
[Theory]
66+
[MemberData(nameof(Enumerable_NotEqualData))]
67+
public void BeEqualTo_With_NotEqual_Should_Throw(string actual, string expected, int index, string message)
68+
{
69+
// Arrange
70+
71+
// Act
72+
void action() => actual.Must().BeEqualTo(expected);
73+
74+
// Assert
75+
var exception = Assert.Throws<StringEqualToAssertionException>(action);
76+
Assert.Equal(actual, exception.Actual);
77+
Assert.Equal(expected, exception.Expected);
78+
Assert.Equal(index, exception.Index);
79+
Assert.Equal(message, exception.Message);
80+
}
81+
}
82+
}

NetFabric.Assertive.UnitTests/NetFabric.Assertive.UnitTests.csproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFrameworks>net461;netcoreapp2.1;netcoreapp3.1</TargetFrameworks>
4+
<TargetFrameworks>net461;netcoreapp2.1;netcoreapp3.1;net5.0</TargetFrameworks>
55
<IsPackable>false</IsPackable>
66
</PropertyGroup>
77

NetFabric.Assertive/Assertions/AssertionsBase.cs

+5-5
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ namespace NetFabric.Assertive
1111
[DebuggerNonUserCode]
1212
public abstract class AssertionsBase
1313
{
14-
protected static void AssertIsEnumerable<TActual, TActualItem>(TActual actual, out EnumerableInfo enumerableInfo)
14+
protected static void AssertIsEnumerable<TActual, TActualItem>(TActual? actual, out EnumerableInfo enumerableInfo)
1515
{
1616
var actualType = typeof(TActual);
1717
if (actualType == typeof(TActualItem[])) // convert TActualItem[] to IList<TActualItem>
@@ -45,7 +45,7 @@ protected static void AssertIsEnumerable<TActual, TActualItem>(TActual actual, o
4545
}
4646
}
4747

48-
protected static void AssertIsAsyncEnumerable<TActual, TActualItem>(TActual actual, out AsyncEnumerableInfo enumerableInfo)
48+
protected static void AssertIsAsyncEnumerable<TActual, TActualItem>(TActual? actual, out AsyncEnumerableInfo enumerableInfo)
4949
{
5050
var actualType = typeof(TActual);
5151
if (actualType.IsAsyncEnumerable(out var temp, out var errors))
@@ -140,7 +140,7 @@ protected static void AssertEnumerableEquality<TActual, TActualItem, TExpected,
140140

141141
var publicCount = typeof(TActual).GetProperty("Count", BindingFlags.Public | BindingFlags.Instance, null, typeof(int), Type.EmptyTypes, null);
142142
var publicIndexer = typeof(TActual).GetProperty("Item", BindingFlags.Public | BindingFlags.Instance, null, typeof(TActualItem), new[] { typeof(int) }, null);
143-
if (publicCount is object && publicIndexer is object)
143+
if (publicCount is not null && publicIndexer is not null)
144144
{
145145
var wrappedActual = new IndexerWrapper<TActual, TActualItem>(actual, publicIndexer);
146146
switch (wrappedActual.Compare(expected, comparer, out var index))
@@ -235,7 +235,7 @@ protected static void AssertEnumerableEquality<TActual, TActualItem, TExpected,
235235
$"'Contains' return false for an item found when using 'System.Collections.Generic.IEnumerable`1[{typeof(TActualItem)}].GetEnumerator()'.");
236236
}
237237

238-
if (doesNotContain is object)
238+
if (doesNotContain is not null)
239239
{
240240
foreach (var item in doesNotContain)
241241
{
@@ -378,7 +378,7 @@ protected static void AssertEnumerableEquality<TActual, TActualItem, TExpected,
378378
}
379379
}
380380

381-
if (doesNotContain is object)
381+
if (doesNotContain is not null)
382382
{
383383
try
384384
{

NetFabric.Assertive/Assertions/AsyncEnumerables/AsyncEnumerableReferenceTypeAssertions.cs

+6-6
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ public class AsyncEnumerableReferenceTypeAssertions<TActual, TActualItem>
1111
: ReferenceTypeAssertionsBase<TActual>
1212
where TActual : class
1313
{
14-
internal AsyncEnumerableReferenceTypeAssertions(TActual Actual, AsyncEnumerableInfo enumerableInfo)
14+
internal AsyncEnumerableReferenceTypeAssertions(TActual? Actual, AsyncEnumerableInfo enumerableInfo)
1515
: base(Actual)
1616
=> EnumerableInfo = enumerableInfo;
1717

@@ -29,25 +29,25 @@ public AsyncEnumerableReferenceTypeAssertions<TActual, TActualItem> BeSameAs<TOt
2929
public AsyncEnumerableReferenceTypeAssertions<TActual, TActualItem> BeNotSameAs<TOther>(TOther other)
3030
=> BeNotSameAs<AsyncEnumerableReferenceTypeAssertions<TActual, TActualItem>, TOther>(this, other);
3131

32-
public AsyncEnumerableReferenceTypeAssertions<TActual, TActualItem> EvaluateTrue(Func<TActual, bool> func)
32+
public AsyncEnumerableReferenceTypeAssertions<TActual, TActualItem> EvaluateTrue(Func<TActual?, bool> func)
3333
=> EvaluateTrue<AsyncEnumerableReferenceTypeAssertions<TActual, TActualItem>>(this, func);
3434

35-
public AsyncEnumerableReferenceTypeAssertions<TActual, TActualItem> EvaluateFalse(Func<TActual, bool> func)
35+
public AsyncEnumerableReferenceTypeAssertions<TActual, TActualItem> EvaluateFalse(Func<TActual?, bool> func)
3636
=> EvaluateFalse<AsyncEnumerableReferenceTypeAssertions<TActual, TActualItem>>(this, func);
3737

3838
public AsyncEnumerableReferenceTypeAssertions<TActual, TActualItem> BeEmpty(bool testRefStructs = true, bool testRefReturns = true)
3939
=> BeEqualTo(Enumerable.Empty<TActualItem>(), testRefStructs, testRefReturns);
4040

41-
public AsyncEnumerableReferenceTypeAssertions<TActual, TActualItem> BeEqualTo<TExpected>(TExpected expected, bool testRefStructs = true, bool testRefReturns = true)
41+
public AsyncEnumerableReferenceTypeAssertions<TActual, TActualItem> BeEqualTo<TExpected>(TExpected? expected, bool testRefStructs = true, bool testRefReturns = true)
4242
where TExpected : IEnumerable<TActualItem>
4343
=> BeEqualTo<TExpected, TActualItem>(expected, (actual, expected) => EqualityComparer<TActualItem>.Default.Equals(actual, expected), testRefStructs, testRefReturns);
4444

45-
public AsyncEnumerableReferenceTypeAssertions<TActual, TActualItem> BeEqualTo<TExpected, TExpectedItem>(TExpected expected, Func<TActualItem, TExpectedItem, bool> comparer, bool testRefStructs = true, bool testRefReturns = true)
45+
public AsyncEnumerableReferenceTypeAssertions<TActual, TActualItem> BeEqualTo<TExpected, TExpectedItem>(TExpected? expected, Func<TActualItem, TExpectedItem, bool> comparer, bool testRefStructs = true, bool testRefReturns = true)
4646
where TExpected : IEnumerable<TExpectedItem>
4747
{
4848
if (Actual is null)
4949
{
50-
if (expected is object)
50+
if (expected is not null)
5151
throw new EqualToAssertionException<TActual, TExpected>(Actual, expected);
5252
}
5353
else

NetFabric.Assertive/Assertions/Enumerables/EnumerableReferenceTypeAssertions.cs

+9-9
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ public class EnumerableReferenceTypeAssertions<TActual, TActualItem>
1111
: ReferenceTypeAssertionsBase<TActual>
1212
where TActual : class
1313
{
14-
internal EnumerableReferenceTypeAssertions(TActual Actual, EnumerableInfo enumerableInfo)
14+
internal EnumerableReferenceTypeAssertions(TActual? Actual, EnumerableInfo enumerableInfo)
1515
: base(Actual)
1616
=> EnumerableInfo = enumerableInfo;
1717

@@ -23,32 +23,32 @@ public EnumerableReferenceTypeAssertions<TActual, TActualItem> BeNull()
2323
public EnumerableReferenceTypeAssertions<TActual, TActualItem> BeNotNull()
2424
=> BeNotNull<EnumerableReferenceTypeAssertions<TActual, TActualItem>>(this);
2525

26-
public EnumerableReferenceTypeAssertions<TActual, TActualItem> BeSameAs<TOther>(TOther other)
26+
public EnumerableReferenceTypeAssertions<TActual, TActualItem> BeSameAs<TOther>(TOther? other)
2727
=> BeSameAs<EnumerableReferenceTypeAssertions<TActual, TActualItem>, TOther>(this, other);
2828

29-
public EnumerableReferenceTypeAssertions<TActual, TActualItem> BeNotSameAs<TOther>(TOther other)
29+
public EnumerableReferenceTypeAssertions<TActual, TActualItem> BeNotSameAs<TOther>(TOther? other)
3030
=> BeNotSameAs<EnumerableReferenceTypeAssertions<TActual, TActualItem>, TOther>(this, other);
3131

32-
public EnumerableReferenceTypeAssertions<TActual, TActualItem> EvaluateTrue(Func<TActual, bool> func)
32+
public EnumerableReferenceTypeAssertions<TActual, TActualItem> EvaluateTrue(Func<TActual?, bool> func)
3333
=> EvaluateTrue<EnumerableReferenceTypeAssertions<TActual, TActualItem>>(this, func);
3434

35-
public EnumerableReferenceTypeAssertions<TActual, TActualItem> EvaluateFalse(Func<TActual, bool> func)
35+
public EnumerableReferenceTypeAssertions<TActual, TActualItem> EvaluateFalse(Func<TActual?, bool> func)
3636
=> EvaluateFalse<EnumerableReferenceTypeAssertions<TActual, TActualItem>>(this, func);
3737

3838
public EnumerableReferenceTypeAssertions<TActual, TActualItem> BeEmpty(bool testRefStructs = true, bool testRefReturns = true)
3939
=> BeEqualTo(Enumerable.Empty<TActualItem>(), testRefStructs, testRefReturns);
4040

41-
public EnumerableReferenceTypeAssertions<TActual, TActualItem> BeEqualTo<TExpected>(TExpected expected, bool testRefStructs = true, bool testRefReturns = true, bool testNonGeneric = true, bool testIndexOf = true, IEnumerable<TActualItem>? doesNotContain = default)
41+
public EnumerableReferenceTypeAssertions<TActual, TActualItem> BeEqualTo<TExpected>(TExpected? expected, bool testRefStructs = true, bool testRefReturns = true, bool testNonGeneric = true, bool testIndexOf = true, IEnumerable<TActualItem>? doesNotContain = default)
4242
where TExpected : IEnumerable<TActualItem>
43-
=> BeEqualTo<TExpected, TActualItem>(expected, (actual, expected) => EqualityComparer<TActualItem>.Default.Equals(actual, expected), testRefStructs, testRefReturns, testNonGeneric, testIndexOf, doesNotContain);
43+
=> BeEqualTo<TExpected, TActualItem>(expected, (actual, expected) => EqualityComparer<TActualItem>.Default.Equals(actual!, expected!), testRefStructs, testRefReturns, testNonGeneric, testIndexOf, doesNotContain);
4444

45-
public EnumerableReferenceTypeAssertions<TActual, TActualItem> BeEqualTo<TExpected, TExpectedItem>(TExpected expected, Func<TActualItem, TExpectedItem, bool> comparer,
45+
public EnumerableReferenceTypeAssertions<TActual, TActualItem> BeEqualTo<TExpected, TExpectedItem>(TExpected? expected, Func<TActualItem?, TExpectedItem?, bool> comparer,
4646
bool testRefStructs = true, bool testRefReturns = true, bool testNonGeneric = true, bool testIndexOf = true, IEnumerable<TActualItem>? doesNotContain = default)
4747
where TExpected : IEnumerable<TExpectedItem>
4848
{
4949
if (Actual is null)
5050
{
51-
if (expected is object)
51+
if (expected is not null)
5252
throw new EqualToAssertionException<TActual, TExpected>(Actual, expected);
5353
}
5454
else

NetFabric.Assertive/Assertions/Primitives/ArrayAssertions.cs

+4-4
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
namespace NetFabric.Assertive
66
{
77
[DebuggerNonUserCode]
8-
public partial class ArrayAssertions<TActualItem>
8+
public class ArrayAssertions<TActualItem>
99
: ReferenceTypeAssertionsBase<TActualItem[]>
1010
{
1111
internal ArrayAssertions(TActualItem[] actual)
@@ -25,10 +25,10 @@ public ArrayAssertions<TActualItem> BeSameAs<TExpected>(TExpected[] expected)
2525
public ArrayAssertions<TActualItem> BeNotSameAs<TExpected>(TExpected[] expected)
2626
=> BeNotSameAs<ArrayAssertions<TActualItem>, TExpected[]>(this, expected);
2727

28-
public ArrayAssertions<TActualItem> EvaluateTrue(Func<TActualItem[], bool> func)
28+
public ArrayAssertions<TActualItem> EvaluateTrue(Func<TActualItem[]?, bool> func)
2929
=> EvaluateTrue<ArrayAssertions<TActualItem>>(this, func);
3030

31-
public ArrayAssertions<TActualItem> EvaluateFalse(Func<TActualItem[], bool> func)
31+
public ArrayAssertions<TActualItem> EvaluateFalse(Func<TActualItem[]?, bool> func)
3232
=> EvaluateFalse<ArrayAssertions<TActualItem>>(this, func);
3333

3434
public ArrayAssertions<TActualItem> BeArrayOf<TType>()
@@ -52,7 +52,7 @@ public ArrayAssertions<TActualItem> BeEqualTo<TExpected, TExpectedItem>(TExpecte
5252
{
5353
if (Actual is null)
5454
{
55-
if (expected is object)
55+
if (expected is not null)
5656
throw new EqualToAssertionException<TActualItem[], TExpected>(Actual, expected);
5757
}
5858
else

NetFabric.Assertive/Assertions/Primitives/ArraySegmentAssertions.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
namespace NetFabric.Assertive
66
{
77
[DebuggerNonUserCode]
8-
public partial class ArraySegmentAssertions<TActualItem>
8+
public class ArraySegmentAssertions<TActualItem>
99
: ValueTypeAssertionsBase<ArraySegment<TActualItem>>
1010
{
1111
internal ArraySegmentAssertions(ArraySegment<TActualItem> actual)

NetFabric.Assertive/Assertions/Primitives/NullableValueTypeAssertions.cs

+3-3
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
namespace NetFabric.Assertive
66
{
77
[DebuggerNonUserCode]
8-
public partial class NullableValueTypeAssertions<TActual>
8+
public class NullableValueTypeAssertions<TActual>
99
: AssertionsBase
1010
where TActual : struct
1111
{
@@ -29,7 +29,7 @@ public NullableValueTypeAssertions<TActual> BeEqualTo(TActual? expected)
2929
? this
3030
: throw new EqualToAssertionException<TActual?, TActual?>(Actual, expected);
3131

32-
public NullableValueTypeAssertions<TActual> BeEqualTo<TExpected>(TExpected expected, Func<TActual?, TExpected, bool> comparer)
32+
public NullableValueTypeAssertions<TActual> BeEqualTo<TExpected>(TExpected? expected, Func<TActual?, TExpected?, bool> comparer)
3333
=> comparer(Actual, expected)
3434
? this
3535
: throw new EqualToAssertionException<TActual?, TExpected>(Actual, expected);
@@ -39,7 +39,7 @@ public NullableValueTypeAssertions<TActual> BeNotEqualTo(TActual? expected)
3939
? throw new NotEqualToAssertionException<TActual?, TActual?>(Actual, expected)
4040
: this;
4141

42-
public NullableValueTypeAssertions<TActual> BeNotEqualTo<TExpected>(TExpected expected, Func<TActual?, TExpected, bool> comparer)
42+
public NullableValueTypeAssertions<TActual> BeNotEqualTo<TExpected>(TExpected? expected, Func<TActual?, TExpected?, bool> comparer)
4343
=> comparer(Actual, expected)
4444
? throw new NotEqualToAssertionException<TActual?, TExpected>(Actual, expected)
4545
: this;

0 commit comments

Comments
 (0)