0

Below is my unit test project. I have created a unit test which will test two object's equality. Object is passed by reference to the method GetbookSetName. GetbookSetName is responsible for creating a new book object as well as assign new name to book.

using Programme;
using Xunit;
using System;

namespace XUnitTestProject1
{
    public class BookTests
    {
        [Fact]
        public void CsharpIsPassbyref()
        {   
            // Get book will return new book object and assigned to book1
            var book1 = GetBook("book1");

            //getbookSetName method accepts book object as reference parameter and book name.
            GetbookSetName(ref book1, "New Book");
        }

        private void GetbookSetName(ref Book book, string name)
        {
            book = new Book(name);
            var book1 = new Book(name);
            Assert.Equal(book, book1);
        }

        Book GetBook(string name)
        {
            return new Book(name);
        }
    }
}

Below is the book class. It has a constructor which initializes the book with it's name.

public class Book
{
    public string Name;
        
    public Book(string name)
    {
        Name = name;
    }
}

Error:

Assert.Equal() Failure
Expected: Book { Name = "New Book" }
Actual: Book { Name = "New Book" }

Stack Trace:
BookTests.GetbookSetName(Book& book, String name) line 55
BookTests.CsharpIsPassbyref() line 47

Tt tt
  • 41
  • 2
  • 7

3 Answers3

0

Reference equality and equality of two objects are different things. See: This question

Assert.equals is used for reference equality checks . It will always return false. See: MS Docs. book and book1 might be objects with the same property values, but they are two different objects and will therefore not pass the assertion.

To check for equality instead of reference equality use Assert.AreEqual

MrCodingB
  • 2,284
  • 1
  • 9
  • 22
0

The code is comparing unique pointers and asserting they are equal, which will always be false.

p

ublic class BookTests
    {
        [Fact]
        public void CsharpIsPassbyref()
        {   
           // Get book will return new book object and assigned to book1
            var book1 = GetBook("book1");  // <<< instance A
           //getbookSetName method accepts book object as reference parameter and book name.
            GetbookSetName(ref book1, "New Book"); // << passing instance A to func
        }

        private void GetbookSetName(ref Book book, string name)
        {
            book = new Book(name);  // <<< overwrite instance A with instance B
            var book1 = new Book(name); // <<< new instance C
            Assert.Equal(book, book1);  // <<< comparing addresses of instance B to instance C
        }

        Book GetBook(string name)
        {
            return new Book(name);
        }

If the code intendeds to compare objects that contain the same internal state, then override the Equals() method or == operator to compare the individual member variable values.

  • You mean the sentence ```book = new Book(name);``` is being overwritten by incoming reference(ref Book book ) from method GetbookSetName, right? Now, ```var book1 = new Book(name);``` sentence will again create a new instance with same properties and name as book object in different memory location. – Tt tt May 15 '21 at 16:08
  • Addresses of ```book``` and ```book1``` should be same as both are pointing to same reference of book and both reference is having same property. So book has pointer location that should be same as book1's pointer location. – Tt tt May 15 '21 at 16:20
  • As both object is having same value of pointers. So the assertion should pass. – Tt tt May 15 '21 at 16:20
0

I ran into this issue and ended up overriding the Equals method in my class that checks each property in both objects to see if they are equal:

public override bool Equals(object obj)
{
     return GetType().GetProperties().All(property => property.GetValue(this) == property.GetValue(obj));
}
Ethan Shoe
  • 466
  • 1
  • 7
  • 20