2009-04-27 45 views
3

我们使用C#和Linq2SQL和MS SQL Server数据库。 我们有一个mockdatacontext来进行一些单元测试。 测试时,根据是否使用“真实”或“模拟”数据库,我们发现了两种不同的行为。“模拟”数据库与“真实”数据库行为之间的差异

方案1:真正的数据库

有5个记录中的数据库:

db = realDatabase 
db.InsertOnSubmit(new record) 

var count1 = db.getTable.Count() 

db.SubmitChanges() 

var count2 = db.getTable.Count() 

COUNT1 = COUNT2 =

方案2:模拟数据库

有5条记录在数据库中:

db= mockDatabase 

db.InsertOnSubmit(new record) 

var count1 = db.getTable.Count() 

db.SubmitChanges() 

var count2 = db.getTable.Count() 

COUNT1 = COUNT2 =

* “模拟” 数据库已经知道的SubmitChanges之前的新纪录( )被调用,所以它被包括在计数中。为了测试,我们需要两种行为是相同的。

有没有其他人遇到过这个问题,你能提出一个解决方案吗?

+0

你的模拟数据库是如何实现的? – 2009-04-27 20:55:52

回答

0

我猜你的模拟数据库(在内存?? ??)不是事务性的,并且InsertOnSubmit方法实际上是插入记录。

7

IMO,这是一个常见的错误,一个试图在测试中模拟。 模拟不是模拟器。它不应该实现类似于原始的逻辑,它应该返回硬编码的结果。

如果模拟行为很复杂,那么最终会测试您的模拟而不是您的业务代码。

我使用RhinoMocks,它应该是这样的:

// arrange 
IList<Record> testdata = new List<Record>() {a, b, c}; 
db = MockRepository.GenerateMock<IDatabase>(); 
db.Stub(x => db.getTable).Return(testdata); 

// act: call your unit under test 

// assert 
db.AssertWasCalled(x => x.InsertOnSubmit(Arg<Record>.Is.Anything)); 
db.AssertWasCalled(x => x.SubmitChanges()); 

它仍然每次都返回相同的列表。对于很多情况,这就足够了。你仍然可以在第二getTable调用返回的其他数据:

db.Stub(x => db.getTable).Return(testdata1); 
db.Stub(x => db.getTable).Return(testdata2); 

它总是具体到一个单一的测试,但是这使得它如此简单。

编辑:

我不得不承认,我不熟悉的LINQ2SQL。在我的例子中被模拟的调用是Linq2Sql调用,这可能不容易被模拟。您可能需要将其放在简单的DAL界面之后。然后你嘲笑这个界面。

相关问题