Свободный NHibernate PersistenceSpecification CheckList - PullRequest
3 голосов
/ 29 ноября 2009

В настоящее время я работаю над проектом колледжа, в котором мы используем Fluent NHibernate. Я работаю над выяснением того, как создать тестирование для наших сущностей и сопоставлений Fluent.

Однако я зашел в тупик, пытаясь понять, как использовать CheckList of PersistenceSpecification.

Проведено модульное тестирование со следующей ошибкой:

MvcShop.Core.Tests.EntitiesTests.ItemTest.CanMapItem threw exception:  NHibernate.PropertyValueException: not-null property references a null or transient valueMvcShop.Core.Entities.ItemPicture.Item.

Тест определяется как:

private IList<ItemPicture> _itemPictures = new List<ItemPicture>()
{
new ItemPicture { Filename = "test.jpg", Title = "Test title", PrimaryPicture = true},
        new ItemPicture { Filename = "test2.jpg", Title = "Test title 2" }
    };

    [TestMethod]
    public void CanMapItem()
    {
        new PersistenceSpecification<Item>(Session)
            .CheckProperty(i => i.Title, "Test item")
            .CheckProperty(i => i.Description, "Test description")
            .CheckProperty(i => i.SalesPrice, (decimal)0.0)
            .CheckList(i => i.ItemPictures, _itemPictures) // Complains that Item on ItemPicture is null.
            .VerifyTheMappings();
    }

Мои отображения определены как:

public ItemMap()
    {
        Table("Item");
        Id(i => i.ItemID).GeneratedBy.Identity().Column("Item_id");
        Map(i => i.ItemNo).Nullable().Length(30);
        Map(i => i.Title).Not.Nullable().Length(250);
        Map(i => i.Description).Nullable();
        Map(i => i.SalesPrice).Not.Nullable().Precision(18);
        Map(i => i.AverageRating).Precision(18).Nullable();
        Map(i => i.Visible).Not.Nullable();
        Map(i => i.Weight).Not.Nullable().Precision(18);
        Map(i => i.TimesPurchased);
        Map(i => i.InStock).Not.Nullable();
        Map(i => i.DateAdded).Not.Nullable();
        HasManyToMany(i => i.ItemCategories).Cascade.All().Inverse().Table("ItemCategoryItem");
        HasMany(i => i.ItemPictures).Cascade.AllDeleteOrphan().Inverse().LazyLoad();
        HasMany(i => i.Comments).Cascade.AllDeleteOrphan().Inverse().LazyLoad();
        HasMany(i => i.Ratings).Inverse().LazyLoad();
    }

public ItemPictureMap()
    {
        Table("ItemPicture");
        Id(i => i.ItemPictureID).GeneratedBy.Identity().Column("ItemPicture_id");
        Map(i => i.Title).Nullable();
        Map(i => i.Filename).Not.Nullable();
        Map(i => i.PrimaryPicture).Not.Nullable();
        References(i => i.Item).Not.Nullable().Column("Item_id");
    }

Я действительно не могу понять, как мне заполнить свойство Item ItemPicture при использовании класса PersistenceSpecification.

Есть идеи?

С наилучшими пожеланиями, Кеннет, Дания

Ответы [ 3 ]

4 голосов
/ 24 ноября 2010

Я думаю, что ItemPicture должен существовать в БД до того, как вы запустите тест для него (согласно документации Fluent: http://wiki.fluentnhibernate.org/Persistence_specification_testing - см. Последнюю строку на этой странице.)

Попытка:

[TestMethod]
public void CanMapItem()
{
    var p1 = new ItemPicture { Filename = "test.jpg", Title = "Test title", PrimaryPicture = true};
    var p2 =  new ItemPicture { Filename = "test2.jpg", Title = "Test title 2" };
    using (var tx = Session.BeginTransaction())
    {
        Session.Save(p1);
        Session.Save(p2);
    };
    new PersistenceSpecification<Item>(Session)
        .CheckProperty(i => i.Title, "Test item")
        .CheckProperty(i => i.Description, "Test description")
        .CheckProperty(i => i.SalesPrice, (decimal)0.0)
        .CheckList(i => i.ItemPictures, new List<ItemPicture> {p1, p2});
        .VerifyTheMappings();
}
2 голосов
/ 18 июля 2011

Контрольный список, похоже, содержит ошибку. Он будет пытаться сохранить детей, прежде чем сохранить родителей, хотя ваши сопоставления верны. Если вместо этого вы используете CheckComponentList, ваш Item будет перенаправлен до ItemPictures, и ваш тест должен пройти.

1 голос
/ 30 ноября 2009

Вам не нужно переопределять GetHashCode и Equals и создавать свой собственный IEqualityComparer. Причина этого заключается в том, что сущности не могут сравниваться по умолчанию, тогда как объект значения может.

Например, DateTime нельзя сравнивать по умолчанию по той простой причине, что они не являются значением, а являются экземпляром со значением и имеют значение datetime1! = Datetime2, даже если их даты в точности совпадают, поэтому вам нужно сделать следующее: сравнить их по ключевым значениям. Для класса, как указано выше. Я полагаю, что Item содержит набор ItemPictures, а затем в вашей реализации IEqualityComparer, когда вы переопределяете equals, вы должны проверить, соответствует ли текущий объект типу ItemPicture и соответствует ли текущий идентификатор ItemPicture другим сторонам ItemPicture.Id. Поскольку код говорит громче слов, я приведу небольшой пример:

[TestMethod]
public void CanMapItem()
{
    new PersistenceSpecification<Item>(Session, new CustomIEqualityComparer())
        .CheckProperty(i => i.Title, "Test item")
        .CheckProperty(i => i.Description, "Test description")
        .CheckProperty(i => i.SalesPrice, (decimal)0.0)
        .CheckList(i => i.ItemPictures, _itemPictures) // Complains that Item on ItemPicture is null.
        .VerifyTheMappings();
}


public class CustomIEqualityComparer: IEqualityComparer
{
    public bool Equals(object x, object y)
    {
        if (x == null || y == null)
        {
            return false;
        }
        if (x is ItemPicture && y is ItemPicture)
        {
            return ((ItemPicture) x).Id == ((ItemPicture) y).Id;
        }
        if(x is DateTime && y is DateTime)
        {
            return ((DateTime)x).Year ==((DateTime)y).Year;
        }
        return x.Equals(y);
    }

    public int GetHashCode(object obj)
    {
        throw new NotImplementedException();
    }
}
...