Search code examples
c#assertionsfluent-assertions

How to check if Dictionary of type class can be verified using ContainValue in Fluent Assertion


I am trying to check Dictionary of type custom class as Value.

I would like to know if my approach of searching for value within Dictionary is correct using ContainValue in Fluent Assertion.

Here is the code

    public static void VerifyDictionary()
    {
        try
        {
            Dictionary<int, Employee> empDict = new Dictionary<int, Employee>
            {
                { 1, new Employee() {EmployeeID = 100,Name="Karthik", EmployeeEmail="karthik@executeautomation.com", EmployeeAddress="Chennai,India"}},
                {2, new Employee() { EmployeeID = 101,Name="Jack",EmployeeEmail="Jack@jill.com",EmployeeAddress="CA"} },
                {3, new Employee() { EmployeeID=102,Name="Sam",EmployeeEmail="Sam@sung.com",EmployeeAddress="SFO"}},
                {4, new Employee() { EmployeeID=103,Name="Max",EmployeeEmail="micro@max.com",EmployeeAddress="India" }}
            };

            empDict.Should().ContainValue(new Employee() { EmployeeID = 10, EmployeeEmail = "micro@max.com", EmployeeAddress = "India", Name = "Max" }, "because thats the information I need");


        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }
    }

Employee Class

public class Employee
{
    public int EmployeeID { get; set; }
    public string Name { get; set; }
    public string EmployeeEmail { get; set; }
    public string EmployeeAddress { get; set; }
}

While I execute this code, I am getting exception as shown

**

Expected dictionary {[1, BDDDemo.Employee], [2, BDDDemo.Employee], [3, BDDDemo.Employee], [4, BDDDemo.Employee]} to contain value 
BDDDemo.Employee
{
   EmployeeAddress = "India"
   EmployeeEmail = "micro@max.com"
   EmployeeID = 10
   Name = "Max"
} because thats the information I need.

**

Please help me understand whats wrong I am doing here.

Thanks,


Solution

  • ContainValue's check for whether a value is in the dictionary or not is based on the Equals method of values in the dictionary.

    In this case Employee does not override Equals so the implementation inherited from Object is used; that is reference equality will be used.

    As an example, the following code would pass:

    var expected = new Employee { EmployeeID = 10 };
    var dictionary = new Dictionary<int, Employee> { {1, expected} };
    dictionary.Should().ContainValue( expected );
    

    This, however, would fail because they are two different instances of Employee even though all their members are the same:

    var expected = new Employee { EmployeeID = 10 };
    var dictionary = new Dictionary<int, Employee> { {1, expected} };
    dictionary.Should().ContainValue( new Employee { EmployeeID = 10 } );
    

    To make this later case pass you could override Equals. However, the entire class is mutable so I cannot recommend that unless you also make whichever member(s) you are using to determine Equality immutable.

    Without modifying the class, your best bet is to use a different assertion, probably along these lines:

    dictionary.Values.Should().Contain(employee => 
        /* Logic for how you want to determine a match */);