2011-11-27 97 views
1

好了,所以这里是我遇到的问题。我有一个存储库的几个单元测试,我个人对其中的所有人都开了绿灯。然而,当我一起运行所有的测试时,第一个测试成功,然后我得到了其他测试的外键约束错误,这只发生在我有多对一关系的地方。我曾尝试与级联选项玩,我删除了第一次测试,看它是否被破坏的试验数据,但所发生的一切是我第一次测试了绿灯,其余的就红了。再次孤立地说,我在所有测试中都获得了绿灯。NHibernate的单元测试无法正常工作在许多对一个表

大部分代码是基于"Your first NHibernate based application"啧啧上NHForge.com

错误是发生在StockTransactionRepository。我试图包含相关代码,如果你需要更多的让我知道。我怀疑这里有些明显的东西。

错误:

NHibernate.Exceptions.GenericADOException : could not insert: [rapidstk_base.Domain.StockTransaction#f305a5d4-9-c6e-bcdf-9d4dd16337ff][SQL: INSERT INTO StockTransaction (stkitm_StockItemToTransact, dcm_StockTransactionAmount, stkloc_StockLocation, dt_StockTransactionDate, Id) VALUES (?,?,?,?,?)] 
    ---->MySql.Data.MySqlClient.MySqlException: Cannot add or update a child row: a foreign key constraint fails (`rpdstkdb`.`stocktransaction`, CONSTRAINT `FK37E1C2103E2BF85C` FOREIGN KEY (`stkitm_StockItemToTransact`) REFERENCES `stockitem` (`ID`)) 

的hbm.xml代码:

<?xml version="1.0" encoding="utf-8" ?> 
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" 
       assembly="rapidstk_base" 
       namespace="rapidstk_base.Domain" 
       auto-import="false"> 
<class name="rapidstk_base.Domain.StockTransaction"> 
    <id name="Id"> 
     <generator class="guid" /> 
    </id> 
    <many-to-one name="stkitm_StockItemToTransact" class="StockItem" cascade="all" /> 
    <property name="dcm_StockTransactionAmount" /> 
    <many-to-one name="stkloc_StockLocation" class="StockLocation" cascade="all" /> 
    <property name="dt_StockTransactionDate" /> 
</class> 
</hibernate-mapping> 


<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" 
       assembly="rapidstk_base" 
       namespace="rapidstk_base.Domain" 
       auto-import="false"> 
<class name="rapidstk_base.Domain.StockItem"> 
    <id name="Id"> 
     <generator class="guid" /> 
    </id> 
     <property name="str_StockItemName" /> 
     <property name="str_StockItemDescription" /> 
     <property name="dtm_StockItemCreationDate" /> 
</class> 

<?xml version="1.0" encoding="utf-8" ?> 
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" 
       assembly="rapidstk_base" 
       namespace="rapidstk_base.Domain" 
       auto-import="false"> 
<class name="rapidstk_base.Domain.StockLocation"> 
    <id name="Id"> 
     <generator class="guid" /> 
    </id> 
    <property name="s_StockLocationName" /> 
    <property name="s_StockLocationDescription" /> 
</class> 
</hibernate-mapping> 

单元测试:

using NUnit.Framework; 
using NHibernate.Cfg; 
using NHibernate.Tool.hbm2ddl; 
using NHibernate; 
using System; 
using System.Collections.Generic; 

using rapidstk_base.Domain; 
using rapidstk_base.Repositories; 
using rapidstk_base; 

namespace rapidstk_base_test 
{ 
[TestFixture] 
public class StockTransactionRepositoryTest 
{ 
    private ISessionFactory _sessionFactory; 
    private Configuration _configuration; 

    private readonly static StockItem[] _stockitems = new[] 
    { 
     new StockItem { str_StockItemName = "Orgone Accumulator", str_StockItemDescription = "Social Integrator." }, 
     new StockItem { str_StockItemName = "Perpetual Dingle", str_StockItemDescription = "Everlasting Bliss." }, 
     new StockItem { str_StockItemName = "Apple", str_StockItemDescription = "Golden Delicious." }, 
     new StockItem { str_StockItemName = "Nepenthe", str_StockItemDescription = "The answer." }, 
     new StockItem { str_StockItemName = "Bobbins Gourd", str_StockItemDescription = "Follow The Gourd." }, 
    }; 

    private readonly static StockLocation[] _stocklocations = new[] 
    { 
     new StockLocation() { s_StockLocationName="Bay 1", s_StockLocationDescription="Upstairs next to the coffee machine."}, 
     new StockLocation() { s_StockLocationName="Bay 2", s_StockLocationDescription="Under the Shrubbery."}, 
     new StockLocation() { s_StockLocationName="Bay Watch", s_StockLocationDescription="Bouncing on the Beach."}, 
     new StockLocation() { s_StockLocationName="My Pocket", s_StockLocationDescription="Lintville."}, 
     new StockLocation() { s_StockLocationName="Secret Lair", s_StockLocationDescription="Next to the coke machine."}, 
    }; 

    private readonly StockTransaction[] _stockTransactions = new[] 
    { 
     new StockTransaction { stkitm_StockItemToTransact = _stockitems[0], stkloc_StockLocation = _stocklocations[0], dcm_StockTransactionAmount = 10.0M }, 
     new StockTransaction { stkitm_StockItemToTransact = _stockitems[1], stkloc_StockLocation = _stocklocations[1], dcm_StockTransactionAmount = -10.0M }, 
     new StockTransaction { stkitm_StockItemToTransact = _stockitems[2], stkloc_StockLocation = _stocklocations[2], dcm_StockTransactionAmount = 1.0M }, 
     new StockTransaction { stkitm_StockItemToTransact = _stockitems[3], stkloc_StockLocation = _stocklocations[3], dcm_StockTransactionAmount = 2.9M }, 
     new StockTransaction { stkitm_StockItemToTransact = _stockitems[4], stkloc_StockLocation = _stocklocations[4], dcm_StockTransactionAmount = 155.0M, dt_StockTransactionDate=DateTime.Parse("2011/11/30") }, 
     new StockTransaction { stkitm_StockItemToTransact = _stockitems[4], stkloc_StockLocation = _stocklocations[4], dcm_StockTransactionAmount = -50.0M, dt_StockTransactionDate=DateTime.Parse("2011/12/01") }, 
     new StockTransaction { stkitm_StockItemToTransact = _stockitems[4], stkloc_StockLocation = _stocklocations[4], dcm_StockTransactionAmount = -50.0M, dt_StockTransactionDate=DateTime.Parse("2011/12/02") }, 
     new StockTransaction { stkitm_StockItemToTransact = _stockitems[4], stkloc_StockLocation = _stocklocations[4], dcm_StockTransactionAmount = -50.0M, dt_StockTransactionDate=DateTime.Parse("2011/12/03") }, 
    }; 

    private void CreateInitialData() 
    { 
     using (ISession session = _sessionFactory.OpenSession()) 
     { 
      using(ITransaction transaction = session.BeginTransaction()) 
      { 
       foreach(var tr in _stockTransactions) 
       { 
        session.Save(tr); 
       } 
       transaction.Commit(); 
      } 
     } 
    } 

    [TestFixtureSetUp] 
    public void TestFixtureSetup() 
    { 
     _configuration = new Configuration(); 
     _configuration.Configure(); 
     _configuration.AddAssembly(typeof(rapidstk_base.Domain.StockTransaction).Assembly); 
     _sessionFactory = _configuration.BuildSessionFactory(); 
    } 

    [SetUp] 
    public void SetupContext() 
    { 
     var schema = new SchemaExport(_configuration); 
     schema.Create(true, true); 
     CreateInitialData(); 
    } 

    [Test] 
    public void CanAddTransaction() 
    { 
     var newStkTransaction = new StockTransaction{ stkitm_StockItemToTransact=_stockitems[0], stkloc_StockLocation=_stocklocations[3], dcm_StockTransactionAmount=42.0M }; 
     IStockTransactionRepository repository = new StockTransactionRepository(); 
     repository.Add(newStkTransaction); 

     using(ISession session = _sessionFactory.OpenSession()) 
     { 
      var fromdb = session.Get<StockTransaction>(newStkTransaction.Id); 
      Assert.IsNotNull(fromdb); 
      Assert.AreNotSame(newStkTransaction, fromdb); 
      Assert.AreEqual(newStkTransaction.stkitm_StockItemToTransact.str_StockItemName, fromdb.stkitm_StockItemToTransact.str_StockItemName); 
      Assert.AreEqual(newStkTransaction.stkitm_StockItemToTransact.str_StockItemDescription, fromdb.stkitm_StockItemToTransact.str_StockItemDescription); 
      Assert.AreEqual(newStkTransaction.stkloc_StockLocation.s_StockLocationName, fromdb.stkloc_StockLocation.s_StockLocationName); 
      Assert.AreEqual(newStkTransaction.stkloc_StockLocation.s_StockLocationDescription, fromdb.stkloc_StockLocation.s_StockLocationDescription); 
      Assert.AreEqual(newStkTransaction.dcm_StockTransactionAmount, fromdb.dcm_StockTransactionAmount); 
     } 

    } 

    [Test] 
    public void CanRemoveTransaction() 
    { 
     IStockTransactionRepository repository = new StockTransactionRepository(); 
     Guid id = _stockTransactions[0].Id; 
     repository.Remove(_stockTransactions[0]); 

     using(ISession session = _sessionFactory.OpenSession()) 
     { 
      var fromdb = session.Get<StockLocation>(id); 
      Assert.IsNull(fromdb); 
     } 
    } 

    [Test] 
    public void CanUpdateTransaction() 
    { 
     IStockTransactionRepository repository = new StockTransactionRepository(); 
     var stkTransaction = _stockTransactions[1]; 
     stkTransaction.dcm_StockTransactionAmount = 150.0M; 
     repository.Update(stkTransaction); 

     using(ISession session = _sessionFactory.OpenSession()) 
     { 
      var fromdb = session.Get<StockTransaction>(stkTransaction.Id); 
      Assert.AreEqual(stkTransaction.dcm_StockTransactionAmount, fromdb.dcm_StockTransactionAmount); 
     } 
    } 

    [Test] 
    public void CanGetAllTransactionForAProduct() 
    { 
     IStockTransactionRepository repository = new StockTransactionRepository(); 
     StockItem queryItem = _stockitems[4]; 
     var fromdb = repository.GetByStockItem(queryItem); 

     Assert.AreEqual(4, fromdb.Count); 
     Assert.IsTrue(IsInCollection(_stockTransactions[5], fromdb)); 
     Assert.IsTrue(IsInCollection(_stockTransactions[6], fromdb)); 
    } 

    private bool IsInCollection(StockTransaction stkTrns, ICollection<StockTransaction> fromdb) 
    { 
     foreach(var item in fromdb) 
      if(stkTrns.Id == item.Id) 
       return true; 
     return false; 
    } 

    [Test] 
    public void CanGetAllTransactionsUpToADate() 
    { 
     IStockTransactionRepository repository = new StockTransactionRepository(); 
     StockItem queryItem = _stockitems[4]; 
     var fromdb = repository.GetByStockItem(queryItem, DateTime.Parse ("2011/12/02")); 

     Assert.AreEqual(3, fromdb.Count); 
     Assert.IsTrue(IsInCollection(_stockTransactions[5], fromdb)); 
     Assert.IsTrue(IsInCollection(_stockTransactions[6], fromdb)); 
     Assert.IsFalse(IsInCollection(_stockTransactions[7], fromdb)); 
    } 

    [Test] 
    public void CanGetAllTransactionsBetweenDates() 
    { 
     IStockTransactionRepository repository = new StockTransactionRepository(); 
     StockItem queryItem = _stockitems[4]; 
     var fromdb = repository.GetByStockItem(queryItem, DateTime.Parse ("2011/12/01"), DateTime.Parse ("2011/12/03")); 

     Assert.AreEqual(3, fromdb.Count); 
     Assert.IsFalse(IsInCollection(_stockTransactions[4], fromdb)); 
     Assert.IsTrue(IsInCollection(_stockTransactions[5], fromdb)); 
     Assert.IsTrue(IsInCollection(_stockTransactions[6], fromdb)); 
     Assert.IsTrue(IsInCollection(_stockTransactions[7], fromdb)); 
    } 
} 
} 

股票交易存储库编号:

using System; 
using System.Collections.Generic; 
using rapidstk_base.Domain; 
using NHibernate; 
using NHibernate.Criterion; 

namespace rapidstk_base.Repositories 
{ 
public class StockTransactionRepository : IStockTransactionRepository 
{ 
    public void Add(StockTransaction stkTransaction) 
    { 
     using(ISession session=NHibernateHelper.OpenSession()) 
      using(ITransaction transaction = session.BeginTransaction()) 
     { 
      session.Save(stkTransaction); 
      transaction.Commit(); 
     } 
    } 

    public void Remove(StockTransaction stkTransaction) 
    { 
     using(ISession session=NHibernateHelper.OpenSession()) 
      using(ITransaction transaction = session.BeginTransaction()) 
     { 
      session.Delete(stkTransaction); 
      transaction.Commit(); 
     } 
    } 

    public void Update(StockTransaction stkTransaction) 
    { 
     using(ISession session = NHibernateHelper.OpenSession()) 
      using(ITransaction transaction = session.BeginTransaction()) 
     { 
      session.Update(stkTransaction); 
      transaction.Commit(); 
     } 
    } 

    public ICollection<StockTransaction> GetByStockItem(StockItem item) 
    { 
     using(ISession session = NHibernateHelper.OpenSession()) 
     { 
      var transactions = session.CreateCriteria(typeof(StockTransaction)) 
           .Add(Restrictions.Eq("stkitm_StockItemToTransact", item)) 
           .List<StockTransaction>(); 
      return transactions; 
     } 
    } 

    public ICollection<StockTransaction> GetByStockItem(StockItem item, DateTime endDate) 
    { 
     using(ISession session = NHibernateHelper.OpenSession()) 
     { 
      var transactions = session.CreateCriteria(typeof(StockTransaction)) 
           .Add(Restrictions.Eq("stkitm_StockItemToTransact", item)) 
           .Add(Restrictions.Le("dt_StockTransactionDate", endDate)) 
           .List<StockTransaction>(); 
      return transactions; 
     } 
    } 

    public ICollection<StockTransaction> GetByStockItem(StockItem item, DateTime startDate, DateTime endDate) 
    { 
     using(ISession session = NHibernateHelper.OpenSession()) 
     { 
      var transactions = session.CreateCriteria(typeof(StockTransaction)) 
           .Add(Restrictions.Eq("stkitm_StockItemToTransact", item)) 
           .Add(Restrictions.Le("dt_StockTransactionDate", endDate)) 
           .Add(Restrictions.Ge("dt_StockTransactionDate", startDate)) 
           .List<StockTransaction>(); 
      return transactions; 
     } 
    } 

    public StockTransactionRepository() 
    { 

    } 
} 
} 

回答

1

我认为发生了什么是因为你的StockItems,StockLocations和Stocktransactions是静态的,NHibernate在第一次测试中将它们与会话关联起来,并将代理替换成任何关联,然后在后续测试中,他们没有坚持正确和你得到这个FK约束错误尝试使他们非静态的,只是你CreateInitialData调用之前对它们进行初始化所以你Seetup可能看起来像:。

[SetUp] 
public void SetupContext() 
{ 
    var schema = new SchemaExport(_configuration); 
    schema.Create(true, true); 
    InitializeData(); //create your StockItems, StockLocations, and StockTransactions 
    CreateInitialData(); 
} 
+0

宾果!干得好,非常感谢。基本上你说了什么,现在我正在全面绿化。 ;-D – user1067800

1

看起来您并没有拆卸回滚事务。请记住,一个多到一的关系将坚持你添加一个项目(它没有经过冲洗一定的时刻。我的猜测是,你有脏数据。只需添加一个拆卸并回滚NHibernate的交易,我认为你应该没问题

+0

嗨,感谢您的贡献。我现在已经实施了拆解,沿着schema.drop(true,true)的方向。而且我在SetupContext()中调用CreateInitialData,在每次测试开始时调用CreateInitialData,并且仍然遇到同样的问题。我已经检查过安装和拆解正在调用,他们是。如果我运行一个测试,然后看看我的数据库我在它的结束一个空数据库,因此它实际上是下降的表格等。还有,当我运行一个测试,我得到绿灯,当我运行了他们全部第一个存储库是绿色的,其余的是rd – user1067800

+0

您可以在第一次测试之后验证数据库是否为空?可能需要通过启动调试器来暂停中间的测试。然后查看数据库。确保您正在查看交易中的数据,而不仅仅是处于已提交状态的数据。 – ryber

+0

是的,我用调试器运行它,它似乎正确地删除表。看起来我的数据被声明为静态,我将数组更改为非静态,并将它们定义在CreateInitialData中,并且现在一直变绿。哇噢!现在我需要做的就是创建我的下一个红色:)感谢您的帮助。 – user1067800