C# 在不覆盖的情况下比较单元测试中的多个对象
C# Comparing Multiple Objects in Unit Testing without Overriding
以下测试在我测试元组时产生错误。
'Assert.AreEqual(test,productRepository.GetById(1))' threw an exception of type 'NUnit.Framework.AssertionException'
1) 我如何在不覆盖的情况下解决这个问题?下面介绍的许多解决方案都需要为每个模型提供覆盖等于功能。这在 500 模型+ 数据库中是不可维护的。 Object.Equals 也不行。
2) 我阅读了有关 Autofixture 的内容,Nunit 或最近的 Autofixture 竞争对手是否有任何特殊方法? (似乎与 deepequals 和 expectedobjects 相比,Autofixture 是最受欢迎的)。还有其他 Nuget 库吗?
这些都要求覆盖,只有一个答案提到Autofixture
- How to Compare two objects in unit test?
- C# - Asserting two objects are equal in unit tests
- c# How to find if two objects are equal
N单元测试
[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);
}
存储库
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);
}
}
型号
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; }
}
为了不覆盖 Equals
方法,您通常会创建 IEqualityComparer<T>
的实现,其中 T
是您要比较的类型,在您的例子中 Product
.
在比较器中,您必须实现 bool Equals(T x, T y)
和 int GetHashCode(T obj)
方法。
你的可能看起来像:
public class ProductComparer : IEqualityComparer<Product>
{
// Implement Equals and GetHashCode
}
然后你可以这样使用它:
var actual = new List<int>();
var expected = new List<int>();
var comparer = new ProductComparer();
Assert.That(actual, Is.EqualTo(expected).Using(comparer));
您正在反对对象相等性的 C# 定义,所以这是一场必败的战斗。您不可避免地需要为每个 classes 定义对象相等性。但是可以用很少的工作来完成它——你在一个基础中定义它 class 并继承。
让我们定义 2 classes :
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
}
public class Product2 : DomainEntityIntPK
{
public string Name { get; set; }
}
在这种情况下,我将从 DomainEntityIntPK 派生所有 "business entity" classes。这就是class,顾及商业平等的概念。
这是单元测试和结果:
[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 );
}
}
缺少的元素当然是基数 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;
}
}
以下测试在我测试元组时产生错误。
'Assert.AreEqual(test,productRepository.GetById(1))' threw an exception of type 'NUnit.Framework.AssertionException'
1) 我如何在不覆盖的情况下解决这个问题?下面介绍的许多解决方案都需要为每个模型提供覆盖等于功能。这在 500 模型+ 数据库中是不可维护的。 Object.Equals 也不行。
2) 我阅读了有关 Autofixture 的内容,Nunit 或最近的 Autofixture 竞争对手是否有任何特殊方法? (似乎与 deepequals 和 expectedobjects 相比,Autofixture 是最受欢迎的)。还有其他 Nuget 库吗?
这些都要求覆盖,只有一个答案提到Autofixture
- How to Compare two objects in unit test?
- C# - Asserting two objects are equal in unit tests
- c# How to find if two objects are equal
N单元测试
[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);
}
存储库
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);
}
}
型号
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; }
}
为了不覆盖 Equals
方法,您通常会创建 IEqualityComparer<T>
的实现,其中 T
是您要比较的类型,在您的例子中 Product
.
在比较器中,您必须实现 bool Equals(T x, T y)
和 int GetHashCode(T obj)
方法。
你的可能看起来像:
public class ProductComparer : IEqualityComparer<Product>
{
// Implement Equals and GetHashCode
}
然后你可以这样使用它:
var actual = new List<int>();
var expected = new List<int>();
var comparer = new ProductComparer();
Assert.That(actual, Is.EqualTo(expected).Using(comparer));
您正在反对对象相等性的 C# 定义,所以这是一场必败的战斗。您不可避免地需要为每个 classes 定义对象相等性。但是可以用很少的工作来完成它——你在一个基础中定义它 class 并继承。
让我们定义 2 classes :
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
}
public class Product2 : DomainEntityIntPK
{
public string Name { get; set; }
}
在这种情况下,我将从 DomainEntityIntPK 派生所有 "business entity" classes。这就是class,顾及商业平等的概念。
这是单元测试和结果:
[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 );
}
}
缺少的元素当然是基数 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;
}
}