1

I wrote this unit test using XUnit and Shouldly. Please note that I replaced parts of the namespace, variable names, properties etc, as the customer is a large public organization.

[Fact]
public async void ValidateCreateXXXX_InvalidIdVersionAndStatus_Should_Fail()
{
    // Arrange
    var XXXX = new XXXX.Microservices.XXXX.Models.XXXX
    {
        Id = 1,
        CreatedDateTime = DateTime.Now,
        CreatedBy = "Test",
        UpdatedDateTime = DateTime.Now,
        UpdatedBy = "Test",
        KlientId = 1,
        Version = 0,
        Status = XXXXStatus.Oprettet
    };
    var sut = new XXXXBusinessRule();

    // Act
    var result = await sut.ValidateCreateXXXX(XXXX);

    // Assert
    result.IsSuccess.ShouldBeFalse();
    result.ResultType.ShouldBe(ResultType.Invalid);
    ((Dictionary<string, string[]>)result.Data).ShouldContainKeyAndValue("Id", new []{ "'Id' must be equal to '0'." });
}

So the problem is that my test fails with the following message:

Shouldly.ShouldAssertException : (Dictionary<string, string[]>)result.Data
should contain key
"Id"
    with value
["'Id' must be equal to '0'."]
    but value was
["'Id' must be equal to '0'."]
   at 

XXXX.Unit.BusinessRule.XXXXBusinessRuleTests.ValidateCreateXXXX_InvalidIdVersionAndStatus_Should_Fail() in C:\Source\XXXX\XXXX-udvikling\Test\XXXX.Unit\BusinessRule\XXXXBusinessRuleTests.cs:line 60
       at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
       at System.Threading.Tasks.Task.<>c.<ThrowAsync>b__139_0(Object state)

Please note that the expected value and the actual value are the exact same. What the heck is happening here? This error doesn't make much sense to me. I have also tried using the ShouldContainKey("Id") which works. So the problem must be the string array?

Can someone help me figure out what I'm doing wrong? All help appreciated.

RonRonDK
  • 425
  • 6
  • 22
  • 3
    I assume that Shouldy compares the array by reference. Since you are newing up the array in your assert, they are technically not the same. You will need to compare the items in the array. – JOSEFtw Aug 25 '21 at 10:40
  • 1
    I just took a poke around [The implementation](https://github.com/shouldly/shouldly/blob/master/src/Shouldly/ShouldlyExtensionMethods/ShouldBeDictionaryTestExtensions.cs)... That will use default equality, which like @JOSEFtw said is by reference. – Flippie van Dyk Aug 25 '21 at 10:47
  • Thanks for your comments both. So I take it that the ShouldContainKeyAndValue() method cannot easily be used when value is a string array. There is also no example on this in the Shouldly documentation. – RonRonDK Aug 25 '21 at 10:52

1 Answers1

2

You can achieve the same with the following assertions:

var errors = result.Data.ShouldBeAssignableTo<Dictionary<string, string[]>>();

errors.ShouldContainKey("Id");

errors["Id"].ShouldBe(new[] { "'Id' must be equal to '0'."})
  1. Rather than casting the result.Data explicitly you can use the ShouldBeAssignableTo to have an assertion on the type as well
  2. You can make sure that the key is present with ShouldContainKey
  3. And finally you can assess the retrieved value with ShouldBe
Peter Csala
  • 17,736
  • 16
  • 35
  • 75
  • 1
    Amazing! That worked. I dont know whether it answered my original question but it is definitely the solution to my issue. Thank you very much for your quick help @Peter Csala – RonRonDK Aug 25 '21 at 12:42