NHibernate单元测试在多对一表上不能正常工作
本文关键字:常工作 工作 不能 单元测试 多对一 NHibernate | 更新日期: 2023-09-27 18:15:56
好的,这就是我遇到的问题。我有几个存储库的单元测试,我对它们都单独开了绿灯。然而,当我一起运行所有测试时,第一个测试成功,然后我得到其他外键约束错误,这只发生在我有多对一关系的地方。我试着玩级联选项,我删除了第一个测试,看看它是否破坏了测试数据,但所发生的一切都是我在第一个测试中得到了绿灯,其余的都变红了。在隔离中我所有的测试都通过了
大部分代码是基于"你的第一个基于NHibernate的应用程序"在NHForge.com上的tut
错误发生在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 ()
{
}
}
}
我认为发生的事情是因为您的StockItems, StockLocations和Stocktransactions是静态的,NHibernate在第一次测试时将它们与会话关联,并将任何关联替换为代理。然后在随后的测试中,它们没有被正确地保存,你会得到这个FK约束错误。尝试使它们非静态,并在CreateInitialData
调用之前初始化它们。所以你的设置可能看起来像:
[SetUp]
public void SetupContext()
{
var schema = new SchemaExport(_configuration);
schema.Create(true, true);
InitializeData(); //create your StockItems, StockLocations, and StockTransactions
CreateInitialData();
}
看起来不像要回滚事务。请记住,在添加项时将持久化多对一关系(不一定要经过刷新)。我猜你有脏数据。只要添加一个teardown并回滚非休眠事务,我想你应该没问题。