在NHibernate的Nunit测试中出现奇怪的失败

本文关键字:失败 NHibernate Nunit 测试 | 更新日期: 2023-09-27 18:17:00

使用NUnit和FluentAssertion运行一个简单的测试,我有以下失败消息:

Expected object to be 
Gedi.Domain.Object.Entity.Persona
{
   Annullato = False
   Descrizione = "Persona1"
   Id = 1
}, but found 
Gedi.Domain.Object.Entity.Persona
{
   Annullato = False
   Descrizione = "Persona1"
   Id = 1
}.

但我看不出有什么不同。哪个可能是失败的原因?

这是测试方法

public void CanSaveAndLoadDocumento()
    {
        //Arrange
        Documento documentoTarget = new Documento();
        Documento documentoActual;
        documentoTarget.Id = fixture.Create<int>();                 
        // Act
        using (IUnitOfWork uow = new UnitOfWork())
        {
            uow.Start();
            documentoTarget.Persona = uow.ServiceRepositoryFor<Persona>().GetById(1);
            uow.DocumentoRepository.Create(documentoTarget);
            uow.Commit();
            uow.CloseConnection();
            uow.Start();
            documentoActual = uow.DocumentoRepository.GetById(documentoTarget.Id);          
            uow.CloseConnection();
        }
        //Assert
        documentoActual.Persona.Should().Be(documentoTarget.Persona);
    }

ID = 1的角色是我直接在数据库中手写的

这是我与NHibernate一起使用的基础存储库

public abstract class RepositoryBase<TEntity, TKey> : IDisposable
    where TEntity : class, IKeyedEntity<TKey>
    where TKey : struct
{
    protected ISession _session;
    public RepositoryBase(ISession session)
    {
        _session = session;         
    }       
    public void Create(TEntity entity)
    {
        _session.SaveOrUpdate(entity);
    }       
    public TEntity GetById(TKey id)
    {
        return _session.Get<TEntity>(id);
    }
}
public class DocumentoRepository : RepositoryBase<Documento, int>
{
    public DocumentoRepository(ISession session)
        : base(session)
    {
    }
}

在NHibernate的Nunit测试中出现奇怪的失败

原因很简单- DocumentoRepository.GetById(documentoTarget.Id)创建Persona实体的新实例而不是返回缓存实例。流畅断言通过引用比较两个实体,因此会出现断言失败。

你可以为你的Persona类实现EqualsGetHashCode。或者使用ShouldBeEquivlentTo来断言对象图等价:

documentoActual.Persona.ShouldBeEquivlentTo(documentoTarget.Persona);

更好的版本:这样,如果两个对象的所有属性都等于

public abstract class EquatableObject<TObject>: IEquatable<TObject>
    where TObject : class   
{
    protected EquatableObject()
    {           
    }
    public override int GetHashCode()
    {
        IEnumerable<FieldInfo> fields = GetFields();
        int startValue = 17;
        int multiplier = 59;
        int hashCode = startValue;
        foreach (FieldInfo field in fields)
        {
            object value = field.GetValue(this);
            if (value != null)
                hashCode = hashCode * multiplier + value.GetHashCode();
        }
        return hashCode;
    }
    public override bool Equals(object obj)
    {
        if (obj == null)
            return false;
        TObject other = obj as TObject;
        return Equals(other);
    }
    public virtual bool Equals(TObject other)
    {
        if (other == null)
            return false;
        Type t = GetType();
        Type otherType = other.GetType();
        if (t != otherType)
            return false;
        FieldInfo[] fields = t.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
        foreach (FieldInfo field in fields)
        {
            object value1 = field.GetValue(other);
            object value2 = field.GetValue(this);
            if (value1 == null)
            {
                if (value2 != null)
                    return false;
            }
            else if (!value1.Equals(value2))
                return false;
        }
        return true;
    }
    private IEnumerable<FieldInfo> GetFields()
    {
        Type t = GetType();
        List<FieldInfo> fields = new List<FieldInfo>();
        while (t != typeof(object))
        {
            fields.AddRange(t.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public));
            t = t.BaseType;
        }
        return fields;
    }
}

已解决添加

public override bool Equals(object obj)
    {
        if (obj == null)
            return false;
        T other = obj as T;
        return Equals(other);
    }

到我的类