最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

c# - How should I compare the values of non-nullable and nullable types using ShouldBe in Shouldly? - Stack Overflow

programmeradmin0浏览0评论

In the following code, o[0].AccountEnabled has type bool while graphUsers[0].AccountEnabled has type bool?.

Without the explicit cast to bool?, I get the following error:

'bool' does not contain a definition for 'ShouldBe' and the best extension method overload 'ShouldBeTestExtensions.ShouldBe<bool?>(bool?, bool?, string?)' requires a receiver of type 'bool?'CS1929

How should I compare the values of non-nullable and nullable types using Shouldly? xUnit has no problems with this using Assert.Equal()

I prefer to not cast the extension method receiver to a nullable type for every such comparison.

Furthermore, how does it even work with the nullable cast ((bool?))? The definition for ShouldBe is:

public static void ShouldBe<T>(
    [NotNullIfNotNull(nameof(expected))] this T? actual,
    [NotNullIfNotNull(nameof(actual))] T? expected,
    string? customMessage = null)
{
    if (ShouldlyConfiguration.CompareAsObjectTypes.Contains(typeof(T).FullName!) || typeof(T) == typeof(string))
        actual.AssertAwesomely(v => Is.Equal(v, expected, new ObjectEqualityComparer<T>()), actual, expected, customMessage);
    else
        actual.AssertAwesomely(v => Is.Equal(v, expected), actual, expected, customMessage);
}

So, if T is bool?, then it would accept arguments of type bool??, which isn't a valid type.

Code:

owners.ShouldSatisfyAllConditions(
    o => o.Count.ShouldBe(graphUsers.Count),
    o => o[0].Id.ShouldBe(Guid.Parse(graphUsers[0].Id!)),
    o => o[0].DisplayName.ShouldBe(graphUsers[0].DisplayName),
    o => o[0].GivenName.ShouldBe(graphUsers[0].GivenName),
    o => o[0].Surname.ShouldBe(graphUsers[0].Surname),
    o => o[0].UserPrincipalName.ShouldBe(graphUsers[0].UserPrincipalName),
    o => o[0].Email.ShouldBe(graphUsers[0].Mail),
    o => ((bool?)o[0].AccountEnabled).ShouldBe(graphUsers[0].AccountEnabled)
);

In the following code, o[0].AccountEnabled has type bool while graphUsers[0].AccountEnabled has type bool?.

Without the explicit cast to bool?, I get the following error:

'bool' does not contain a definition for 'ShouldBe' and the best extension method overload 'ShouldBeTestExtensions.ShouldBe<bool?>(bool?, bool?, string?)' requires a receiver of type 'bool?'CS1929

How should I compare the values of non-nullable and nullable types using Shouldly? xUnit has no problems with this using Assert.Equal()

I prefer to not cast the extension method receiver to a nullable type for every such comparison.

Furthermore, how does it even work with the nullable cast ((bool?))? The definition for ShouldBe is:

public static void ShouldBe<T>(
    [NotNullIfNotNull(nameof(expected))] this T? actual,
    [NotNullIfNotNull(nameof(actual))] T? expected,
    string? customMessage = null)
{
    if (ShouldlyConfiguration.CompareAsObjectTypes.Contains(typeof(T).FullName!) || typeof(T) == typeof(string))
        actual.AssertAwesomely(v => Is.Equal(v, expected, new ObjectEqualityComparer<T>()), actual, expected, customMessage);
    else
        actual.AssertAwesomely(v => Is.Equal(v, expected), actual, expected, customMessage);
}

So, if T is bool?, then it would accept arguments of type bool??, which isn't a valid type.

Code:

owners.ShouldSatisfyAllConditions(
    o => o.Count.ShouldBe(graphUsers.Count),
    o => o[0].Id.ShouldBe(Guid.Parse(graphUsers[0].Id!)),
    o => o[0].DisplayName.ShouldBe(graphUsers[0].DisplayName),
    o => o[0].GivenName.ShouldBe(graphUsers[0].GivenName),
    o => o[0].Surname.ShouldBe(graphUsers[0].Surname),
    o => o[0].UserPrincipalName.ShouldBe(graphUsers[0].UserPrincipalName),
    o => o[0].Email.ShouldBe(graphUsers[0].Mail),
    o => ((bool?)o[0].AccountEnabled).ShouldBe(graphUsers[0].AccountEnabled)
);
Share Improve this question edited Feb 2 at 17:47 Mark Seemann 233k49 gold badges447 silver badges775 bronze badges asked Feb 2 at 17:20 ShuzhengShuzheng 14k29 gold badges120 silver badges229 bronze badges
Add a comment  | 

2 Answers 2

Reset to default 1

I don't really know Shouldly, but it looks as though you can use either ShouldBeAssignableTo or ShouldBeEquivalentTo if you don't want to use C#'s built-in cast syntax.

This test passes:

[Theory]
[InlineData(true)]
[InlineData(false)]
public void Test(bool b)
{
    bool? bOrNull = b;
    b.ShouldBeAssignableTo<bool?>().ShouldBe(bOrNull);
    b.ShouldBeEquivalentTo(bOrNull);
}

I'd probably prefer the second option myself.

In my opinion, you could split this assertion in two parts:

  • assert that nullable value is not null (since you expect it to be equal to bool, so it has to have a value)
  • assert that value of nullable bool is expected With Shouldly, it would look like:
[Fact]
public void Test1()
{
    bool? nb = true;
    bool b = true;

    nb.ShouldNotBeNull();
    b.ShouldBe(nb.Value);
}
发布评论

评论列表(0)

  1. 暂无评论