NHibernate测试策略:每个根或每个类/映射一个测试套件

时间:2012-11-14 21:23:59

标签: unit-testing nhibernate repository sharp-architecture convention-over-configur

鉴于大多数真实世界的应用程序在实体之间的关系相当复杂,测试单个类映射有多大价值?似乎真正有价值的是,NHibernate测试应该围绕检索,持久化和删除整个对象图,从聚合根级别开始(即Customer - > Order - > OrderDetails)。但是,如果我沿着这条路前进,似乎我必须在对象树中的每个可想象的级别测试CRUD操作,以验证“整体”按预期工作;导致测试爆炸:

  • 删除客户
  • 删除订单
  • 删除OrderItem
  • 插入客户
  • 插入订单
  • 插入OrderItem

所以,除非我遗漏了一些我非常喜欢的东西,否则我的选择是:

  1. 为每个类/映射编写一个fixture组件
    • 优点:编写CRUD操作更简单
    • 缺点:测试值减少,因为它们无法保证整个聚合根源 正在坚持
  2. 为每个对象图写一个夹具套件
    • 缺点:测试/爆炸测试场景更难测试
    • 优点:作为测试的更高价值,因为他们从应用程序的角度测试持久性(即针对统一/集成对象图测试突变)
  3. 如果完全相关的话,我正在使用NHibernate.Mapping.ByCode ConventionModelMapper来使用约定生成映射。

1 个答案:

答案 0 :(得分:1)

是的,在测试我的映射是否按预期工作时,我会在课程级别进行测试并测试每个类的关系。

例如,如果我有一个Customer对象,其中包含Order对象列表,我会为Customer对象编写集成测试,以确保我可以对该对象执行所有CRUD操作。然后我会为Customer对象拥有的所有关系编写测试,例如有一个Orders,Addresses等列表。这些测试将涵盖诸如级联插入/更新/删除之类的内容以及急切地获取这些子集合的能力。查询。

所以虽然我在类级别进行测试,因为我正在测试每个类的所有关系,但我在技术上测试整个对象图,只要我在每个测试中继续这个测试行为每个映射的类。

更新(添加简要示例):

public class Customer
{
    public int CustomerId { get; set; }
    public string CompanyName { get; set; }
    public IList<Address> Addresses { get; set; }
    public IList<Order> Orders { get; set; }
}

public class Address
{
    public int AddressId { get; set; }
}

public class Order
{
    public int OrderId { get; set; }
    public string Status { get; set; }
    public IList<OrderDetail> OrderDetails { get; set; }
}

public class OrderDetail
{
    public int OrderDetailId { get; set; }
    public string City { get; set; }
}

[TestFixture]
public class CustomerMappingTests
{
    private ISession session;

    [SetUp]
    public void SetUp()
    {
        session = UnitOfWork.Current.GetSession();
    }

    [TearDown]
    public void TearDown()
    {
        session.Dispose();
    }

    [Test]
    public void CanGetCustomer()
    {
        // Arrange
        const int customerId = 1;

        // Act
        var customer = session.Query<Customer>()
            .Where( x => x.CustomerId == customerId )
            .FirstOrDefault();

        // Assert
        Assert.NotNull( customer );
        Assert.That( customer.CustomerId == customerId );
    }

    [Test]
    public void CanGetCustomerAddresses()
    {
        // Arrange
        const int customerId = 1;

        // Act
        var customer = session.Query<Customer>()
            .Where( x => x.CustomerId == customerId )
            .Fetch( x => x.Addresses )
            .FirstOrDefault();

        // Assert
        Assert.NotNull( customer.Addresses.Count > 0 );
    }

    [Test]
    public void CanGetCustomerOrders()
    {
        // Arrange
        const int customerId = 1;

        // Act
        var customer = session.Query<Customer>()
            .Where( x => x.CustomerId == customerId )
            .Fetch( x => x.Orders )
            .FirstOrDefault();

        // Assert
        Assert.NotNull( customer.Orders.Count > 0 );
    }

    [Test]
    public void CanSaveCustomer()
    {
        // Arrange
        const string companyName = "SnapShot Corporation";
        var customer = new Customer { CompanyName = companyName };

        // Act
        session.Save( customer );

        session.Flush(); // Update the database right away
        session.Clear(); // Clear cache

        var customer2 = session.Query<Customer>()
            .Where( x => x.CompanyName == companyName )
            .FirstOrDefault();

        // Assert
        Assert.NotNull( customer2 );
        Assert.That( customer2.CompanyName == companyName );
    }
}