1

The following test creates error when I test tuples.

'Assert.AreEqual(test,productRepository.GetById(1))' threw an exception of type 'NUnit.Framework.AssertionException'

1) How would I resolve this without overriding? Many solutions presented below require an override equals function for each model. This is not maintainable in a 500 model+ database. Object.Equals does not work either.

2) I read about Autofixture, is there any special method in Nunit or recent competitors to Autofixture? (seems like Autofixture is the most popular compared to deepequals and expectedobjects). Are there other Nuget libraries?

These all ask to override, only one answer mentions Autofixture

NUnit Test

[Test]
public void TestProducts()
{
    var options = new DbContextOptionsBuilder<ElectronicsContext>()
        .UseInMemoryDatabase(databaseName: "Products Test")
        .Options;

    using (var context = new ElectronicsContext(options))
    {
        //DbContextOptionsBuilder<ElectronicsContext> context = new DbContextOptionsBuilder<ElectronicsContext>()

        context.Product.Add(new Product { ProductId = 1, ProductName = "TV", ProductDescription = "TV testing", ImageLocation = "test" });
        context.SaveChanges();
        ProductRepository productRepository = new ProductRepository(context);
        var test = new Product
            {ProductId = 1, ProductName = "TV", ProductDescription = "TV testing", ImageLocation = "test"};

       **//This works**
        Assert.AreEqual("TV", productRepository.GetById(1).ProductName);

       **//This Fails**
        Assert.AreEqual(test,productRepository.GetById(1));

       **//This Fails**
        Assert.AreEqual(Object.Equals(test, productRepository.GetById(1)), 1);
    }

Repository

public class ProductRepository : IProductRepository<Product>
{
    private readonly ElectronicsContext _context;
    public ProductRepository(ElectronicsContext context)
    {
        _context = context;
    }

    public IEnumerable<Product> GetAllProduct()
    {
        return _context.Product.ToList();
    }

    public IQueryable<Product> Products => _context.Product;

    public Product GetById(int productid)
    {
        return _context.Product.Find(productid);

    }
}

Model

public partial class Product
{
    public int ProductId { get; set; }
    public string ProductName { get; set; }
    public string ProductDescription { get; set; }
    public string ImageLocation { get; set; }

    public int? ProductCategoryId { get; set; }
    public virtual ProductCategory ProductCategory { get; set; }
}
  • Did you read the docs? [NUnit: Equal Constraint](https://github.com/nunit/docs/wiki/EqualConstraint) – Sir Rufo Oct 18 '18 at 04:43
  • How does the software you are testing implement equality among products? Why can't you use the same method, which would be the most usual approach. – Charlie Oct 18 '18 at 16:14

2 Answers2

1

So as not to override the Equals method, you would typically create an implementation of IEqualityComparer<T> where T is the type you want to compare, in your case Product.

In the comparer you have to implement the bool Equals(T x, T y) and int GetHashCode(T obj) methods.

Yours may look something like:

public class ProductComparer : IEqualityComparer<Product>
{
    // Implement Equals and GetHashCode
}

Then you can use it like this:

var actual = new List<int>();
var expected = new List<int>();
var comparer = new ProductComparer();

Assert.That(actual, Is.EqualTo(expected).Using(comparer));
Hayden Hall
  • 346
  • 3
  • 6
0

You're fighting against the C# definition of object equality, so it's a losing battle. You inevitably need to define object equality for each of your classes. But it is possible to do it with little work - you define it in a base class and inherit.

Let's define 2 classes :

public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class Product2 : DomainEntityIntPK
{
    public string Name { get; set; }
}

In this case I would derive all my "business entity" classes from DomainEntityIntPK. This is the class that takes care of the concept of business equality.

Here are the unit tests and the results:

[TestFixture]
public class UnitTest1
{
    [Test]
    public void TestMethodProduct()
    {
        Product p1 = new Product{ Id=1, Name="Foo" };
        Product p2 = new Product{ Id=1, Name="Foo" };
        Assert.AreEqual( p1, p2 );
    }

    [Test]
    public void TestMethodProduct2()
    {
        Product2 p1 = new Product2{ Id=1, Name="Foo" };
        Product2 p2 = new Product2{ Id=1, Name="Foo" };
        Assert.AreEqual( p1, p2 );
    }
}

enter image description here

And the missing element is, of course, the base class :

public abstract class DomainEntityIntPK
{
    public int Id { get; set; }

    public static bool operator ==( DomainEntityIntPK lhs, DomainEntityIntPK rhs )
    {
        return Equals( lhs, rhs );
    }

    public static bool operator !=( DomainEntityIntPK lhs, DomainEntityIntPK rhs )
    {
        return !Equals( lhs, rhs );
    }

    public override Boolean Equals( object obj )
    {
        DomainEntityIntPK other = obj as DomainEntityIntPK;
        if( other == null ) return false;

        Boolean thisIsNew = Id == 0;
        Boolean otherIsNew = other.Id == 0;
        if( thisIsNew && otherIsNew )
        {
            Boolean referenceEquals =  ReferenceEquals( this, other );
            return referenceEquals;
        }

        Boolean idEquals = Id.Equals( other.Id );
        return idEquals;
    }
}
Mark Willis
  • 818
  • 12
  • 19