Skip to content

Commit 51d3a0f

Browse files
committed
Added unit tests of CompareTo, Generic and Collection assert extensions.
1 parent 057e005 commit 51d3a0f

5 files changed

Lines changed: 353 additions & 9 deletions

File tree

src/Asserting/GenericAssertExtensions.cs renamed to src/Asserting/CollectionAssertExtensions.cs

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,61 @@
88
namespace Egil.RazorComponents.Testing.Asserting
99
{
1010
/// <summary>
11-
/// Generic test assertions
11+
/// Collection test assertions
1212
/// </summary>
1313
public static class GenericAssertExtensions
1414
{
15+
/// <summary>
16+
/// Verifies that <paramref name="actual"/> is not null
17+
/// and returns <paramref name="actual"/> again.
18+
/// </summary>
19+
/// <returns>Returns <paramref name="actual"/> if it is not null.</returns>
20+
public static T ShouldNotBeNull<T>([NotNullIfNotNull("actual")]this T? actual) where T : class
21+
{
22+
if (actual is null)
23+
throw new XunitException($"{nameof(ShouldNotBeNull)}() Failure");
24+
return actual;
25+
}
26+
27+
/// <summary>
28+
/// Verifies that <paramref name="actual"/> is not null
29+
/// and returns <paramref name="actual"/> again.
30+
/// </summary>
31+
/// <returns>Returns <paramref name="actual"/> if it is not null.</returns>
32+
public static T ShouldNotBeNull<T>([NotNullIfNotNull("actual")]this T? actual) where T : struct
33+
{
34+
if (actual is null)
35+
throw new XunitException($"{nameof(ShouldNotBeNull)}() Failure");
36+
return actual.Value;
37+
}
38+
39+
/// <summary>
40+
/// Verifies that a nullable <paramref name="actual"/> is not null
41+
/// and of type <typeparamref name="T"/>.
42+
/// </summary>
43+
/// <returns>Returns <paramref name="actual"/> as <typeparamref name="T"/>.</returns>
44+
public static T ShouldBeOfType<T>([NotNullIfNotNull("actual")]this object? actual)
45+
{
46+
return Assert.IsType<T>(actual);
47+
}
48+
49+
/// <summary>
50+
/// Verifies that a non nullable struct is the same as its nullable counter part.
51+
/// </summary>
52+
public static void ShouldBe<T>(this T actual, T? expected)
53+
where T : struct
54+
{
55+
Assert.Equal(expected, actual);
56+
}
57+
}
58+
59+
/// <summary>
60+
/// Collection test assertions
61+
/// </summary>
62+
public static class CollectionAssertExtensions
63+
{
64+
65+
1566
/// <summary>
1667
/// Verifies that a collection contains exactly a given number of elements, which
1768
/// meet the criteria provided by the element inspectors.

src/Asserting/HtmlEqualException.cs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,6 @@ namespace Xunit.Sdk
1616
[SuppressMessage("Design", "CA1032:Implement standard exception constructors", Justification = "<Pending>")]
1717
public class HtmlEqualException : AssertActualExpectedException
1818
{
19-
/// <summary>
20-
/// Creates an instance of the <see cref="HtmlEqualException"/> type.
21-
/// </summary>
22-
public HtmlEqualException(IEnumerable<IDiff> diffs, IMarkupFormattable expected, IMarkupFormattable actual, string? userMessage, Exception innerException)
23-
: base(PrintHtml(expected), PrintHtml(actual), CreateUserMessage(diffs, userMessage), "Expected HTML", "Actual HTML", innerException)
24-
{
25-
}
26-
2719
/// <summary>
2820
/// Creates an instance of the <see cref="HtmlEqualException"/> type.
2921
/// </summary>
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Reflection;
5+
using System.Text;
6+
using System.Threading.Tasks;
7+
using AngleSharp.Dom;
8+
using Egil.RazorComponents.Testing.SampleComponents;
9+
using Egil.RazorComponents.Testing.TestUtililities;
10+
using Shouldly;
11+
using Xunit;
12+
13+
namespace Egil.RazorComponents.Testing.Asserting
14+
{
15+
public class CompareToDiffingExtensionsTest : ComponentTestFixture
16+
{
17+
/// <summary>
18+
/// Returns an array of arrays containing:
19+
/// (MethodInfo methodInfo, string argName, object[] methodArgs)
20+
/// </summary>
21+
/// <returns></returns>
22+
public static IEnumerable<object[]> GetCompareToMethods()
23+
{
24+
var methods = typeof(CompareToExtensions)
25+
.GetMethods()
26+
.Where(x => x.Name.Equals(nameof(CompareToExtensions.CompareTo), StringComparison.Ordinal))
27+
.ToList();
28+
29+
foreach (var method in methods)
30+
{
31+
var p1Info = method.GetParameters()[0];
32+
var p2Info = method.GetParameters()[1];
33+
object p1 = p1Info.ParameterType.ToMockInstance();
34+
object p2 = p2Info.ParameterType.ToMockInstance();
35+
36+
yield return new object[] { method, p1Info.Name!, new object[] { null!, p2! } };
37+
yield return new object[] { method, p2Info.Name!, new object[] { p1!, null! } };
38+
}
39+
}
40+
41+
[Theory(DisplayName = "CompareTo null values throws")]
42+
[MemberData(nameof(GetCompareToMethods))]
43+
public void Test001(MethodInfo methodInfo, string argName, object[] args)
44+
{
45+
Should.Throw<TargetInvocationException>(() => methodInfo.Invoke(null, args))
46+
.InnerException
47+
.ShouldBeOfType<ArgumentNullException>()
48+
.ParamName.ShouldBe(argName);
49+
}
50+
51+
[Fact(DisplayName = "CompareTo with rendered fragment and string")]
52+
public void Test002()
53+
{
54+
var rf1 = RenderComponent<Simple1>((nameof(Simple1.Header), "FOO"));
55+
var rf2 = RenderComponent<Simple1>((nameof(Simple1.Header), "BAR"));
56+
57+
rf1.CompareTo(rf2.GetMarkup()).Count.ShouldBe(1);
58+
}
59+
60+
[Fact(DisplayName = "CompareTo with rendered fragment and rendered fragment")]
61+
public void Test003()
62+
{
63+
var rf1 = RenderComponent<Simple1>((nameof(Simple1.Header), "FOO"));
64+
var rf2 = RenderComponent<Simple1>((nameof(Simple1.Header), "BAR"));
65+
66+
rf1.CompareTo(rf2).Count.ShouldBe(1);
67+
}
68+
69+
[Fact(DisplayName = "CompareTo with INode and INodeList")]
70+
public void Test004()
71+
{
72+
var rf1 = RenderComponent<Simple1>((nameof(Simple1.Header), "FOO"));
73+
var rf2 = RenderComponent<Simple1>((nameof(Simple1.Header), "BAR"));
74+
75+
var elm = rf1.Find("h1");
76+
elm.CompareTo(rf2.GetNodes()).Count.ShouldBe(1);
77+
}
78+
79+
80+
[Fact(DisplayName = "CompareTo with INodeList and INode")]
81+
public void Test005()
82+
{
83+
var rf1 = RenderComponent<Simple1>((nameof(Simple1.Header), "FOO"));
84+
var rf2 = RenderComponent<Simple1>((nameof(Simple1.Header), "BAR"));
85+
86+
var elm = rf1.Find("h1");
87+
rf2.GetNodes().CompareTo(elm).Count.ShouldBe(1);
88+
}
89+
}
90+
}
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using Shouldly;
4+
using Xunit;
5+
using Xunit.Sdk;
6+
7+
namespace Egil.RazorComponents.Testing.Asserting
8+
{
9+
public class GenericAssertExtensions
10+
{
11+
[Fact(DisplayName = "ShouldNotBeNull throws exception when input is class and null")]
12+
public void Test001()
13+
{
14+
Exception? exception = null;
15+
object? input = null;
16+
try
17+
{
18+
input.ShouldNotBeNull();
19+
}
20+
catch (Exception ex)
21+
{
22+
exception = ex;
23+
}
24+
25+
var actual = exception.ShouldBeOfType<XunitException>();
26+
actual.Message.ShouldContain("ShouldNotBeNull");
27+
}
28+
29+
[Fact(DisplayName = "ShouldNotBeNull throws exception when input is struct and null")]
30+
public void Test002()
31+
{
32+
Exception? exception = null;
33+
int? input = null;
34+
try
35+
{
36+
input.ShouldNotBeNull();
37+
}
38+
catch (Exception ex)
39+
{
40+
exception = ex;
41+
}
42+
43+
var actual = exception.ShouldBeOfType<XunitException>();
44+
actual.Message.ShouldContain("ShouldNotBeNull");
45+
}
46+
47+
[Fact(DisplayName = "ShouldNotBeNull returns input is class and it is not null")]
48+
public void Test003()
49+
{
50+
object? input = new object();
51+
var output = input.ShouldNotBeNull();
52+
output.ShouldBe(input);
53+
}
54+
55+
[Fact(DisplayName = "ShouldNotBeNull returns input is struct and it is not null")]
56+
public void Test004()
57+
{
58+
int? input = 42;
59+
var output = input.ShouldNotBeNull();
60+
output.ShouldBe(input);
61+
}
62+
63+
[Fact(DisplayName = "ShouldBeOfType throws when actual is a different type")]
64+
public void Test005()
65+
{
66+
Exception? exception = null;
67+
try
68+
{
69+
"foo".ShouldBeOfType<int>();
70+
}
71+
catch (Exception ex)
72+
{
73+
exception = ex;
74+
}
75+
76+
Assert.IsType<IsTypeException>(exception);
77+
}
78+
79+
[Fact(DisplayName = "ShouldBeOfType returns input when type is as expected")]
80+
public void Test006()
81+
{
82+
object? input = "foo";
83+
var actual = input.ShouldBeOfType<string>();
84+
actual.ShouldBe(input);
85+
}
86+
}
87+
}
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
using Shouldly;
7+
using Xunit;
8+
using Xunit.Sdk;
9+
10+
namespace Egil.RazorComponents.Testing.Asserting
11+
{
12+
public class GenericCollectionAssertExtensionsTest
13+
{
14+
[Fact(DisplayName = "ShouldAllBe for Action<T> throws CollectionException when " +
15+
"the number of element inspectors does not match the " +
16+
"number of items in the collection")]
17+
public void Test001()
18+
{
19+
Exception? exception = null;
20+
21+
var collection = new string[] { "foo", "bar" };
22+
try
23+
{
24+
collection.ShouldAllBe(x => { });
25+
}
26+
catch (Exception ex)
27+
{
28+
exception = ex;
29+
};
30+
31+
var actual = exception.ShouldNotBeNull().ShouldBeOfType<CollectionException>();
32+
actual.ActualCount.ShouldBe(collection.Length);
33+
actual.ExpectedCount.ShouldBe(1);
34+
}
35+
36+
[Fact(DisplayName = "ShouldAllBe for Action<T> throws CollectionException if one of " +
37+
"the element inspectors throws")]
38+
public void Test002()
39+
{
40+
Exception? exception = null;
41+
42+
var collection = new string[] { "foo", "bar" };
43+
try
44+
{
45+
collection.ShouldAllBe(x => { }, x => throw new Exception());
46+
}
47+
catch (Exception ex)
48+
{
49+
exception = ex;
50+
};
51+
52+
var actual = exception.ShouldNotBeNull().ShouldBeOfType<CollectionException>();
53+
actual.IndexFailurePoint.ShouldBe(1);
54+
}
55+
56+
[Fact(DisplayName = "ShouldAllBe for Action<T, int> throws CollectionException when " +
57+
"the number of element inspectors does not match the " +
58+
"number of items in the collection")]
59+
public void Test003()
60+
{
61+
Exception? exception = null;
62+
63+
var collection = new string[] { "foo", "bar" };
64+
try
65+
{
66+
collection.ShouldAllBe((x, i) => { });
67+
}
68+
catch (Exception ex)
69+
{
70+
exception = ex;
71+
};
72+
73+
var actual = exception.ShouldNotBeNull().ShouldBeOfType<CollectionException>();
74+
actual.ActualCount.ShouldBe(collection.Length);
75+
actual.ExpectedCount.ShouldBe(1);
76+
}
77+
78+
[Fact(DisplayName = "ShouldAllBe for Action<T, int> throws CollectionException if one of " +
79+
"the element inspectors throws")]
80+
public void Test004()
81+
{
82+
Exception? exception = null;
83+
84+
var collection = new string[] { "foo", "bar" };
85+
try
86+
{
87+
collection.ShouldAllBe((x, i) => { }, (x, i) => throw new Exception());
88+
}
89+
catch (Exception ex)
90+
{
91+
exception = ex;
92+
};
93+
94+
var actual = exception.ShouldNotBeNull().ShouldBeOfType<CollectionException>();
95+
actual.IndexFailurePoint.ShouldBe(1);
96+
}
97+
98+
[Fact(DisplayName = "ShouldAllBe for Action<T> passes elements to " +
99+
"the element inspectors in the order of collection")]
100+
public void Test005()
101+
{
102+
var collection = new string[] { "foo", "bar" };
103+
104+
collection.ShouldAllBe(
105+
x => x.ShouldBe(collection[0]),
106+
x => x.ShouldBe(collection[1])
107+
);
108+
}
109+
110+
[Fact(DisplayName = "ShouldAllBe for Action<T, int> passes elements to " +
111+
"the element inspectors in the order of collection, " +
112+
"with the matching index")]
113+
public void Test006()
114+
{
115+
var collection = new string[] { "foo", "bar" };
116+
117+
collection.ShouldAllBe(
118+
(x, i) => { x.ShouldBe(collection[0]); i.ShouldBe(0); },
119+
(x, i) => { x.ShouldBe(collection[1]); i.ShouldBe(1); }
120+
);
121+
}
122+
123+
}
124+
}

0 commit comments

Comments
 (0)