Search code examples
c#moqxunit

XUnit Mocking Passing and Asserting a Collection


New to XUnit and attempting to test the following method but test is failing. I believe the reason is that a new instance of the data is created when the assert is called. So even thought the results are the same the object reference is not.

When a new record is added to the collection, it is supposed to returned the same record added.

Employee Data Class:

    public class EmployeeData
    {
        public int Id { get; set; }
        public string LastName { get; set; }
        public string FirstName { get; set; }
        public string Title { get; set; }

    }

Method to test:

        public List<EmployeeData> Add(List<EmployeeData> employees)
        {

            foreach(var employee in employees)
            {
                data.Add(new EmployeeData() { Id = newId(), 
                        FirstName = employee.FirstName, LastName = employee.LastName, 
                        Title = employee.Title });
            }

            return data;
        }

Test Method:

        [Fact]
        public void Add()
        {
            // Arrange
            var data = new List<EmployeeData>();

            data.Add(new EmployeeData() { Id = 1, FirstName = "Adams", LastName = "John", Title = "Fireman" });

            // Mocking the employee class constructor arguments.
            var mockLogging = new Mock<ILogger<DataService>>();
            var mockConfig = new Mock<IConfiguration>();
            var sut = new Employee(mockLogging.Object, mockConfig.Object);

            var result = sut.Add(data);

            // Assert should return the exact data inputted
            Assert.Equal(result, data);
        }

Test Result:

  Message: 
Assert.Equal() Failure
Expected: List<EmployeeData> [EmployeeData { FirstName = "Adams", Id = 1, LastName = "John", Title = "Fireman" }]
Actual:   List<EmployeeData> [EmployeeData { FirstName = "Adams", Id = 1, LastName = "John", Title = "Fireman" }]

Solution

  • What does it mean that EmployeeData equals EmployeeData? You can override Equals methods in the EmployeeData class.

            public override bool Equals(object obj)
            {
                return this.FirstName == ((EmployeeData)obj).FirstName;
            }
    

    The second option is to pass IEqualityComparer<T> to the Equal method.

        public class GenericCompare<T> : IEqualityComparer<T> where T : class
        {
            private Func<T, object> _expr { get; set; }
            public GenericCompare(Func<T, object> expr)
            {
                this._expr = expr;
            }
            public bool Equals(T x, T y)
            {
                var first = _expr.Invoke(x);
                var sec = _expr.Invoke(y);
                if (first != null && first.Equals(sec))
                    return true;
                else
                    return false;
            }
            public int GetHashCode(T obj)
            {
                return obj.GetHashCode();
            }
        }
    

    And use it:

    Assert.Equal<EmployeeData>(result, data, new GenericCompare<EmployeeData>(x => x.Id));
    

    Copy pasted GenericCompare from https://stackoverflow.com/a/23623976/6629020