“模拟”数据库与“真实”数据库行为之间的差异

我们将C#和Linq2SQL与MS SQL Server数据库一起使用。 我们有一个mockdatacontext来进行一些unit testing。 在测试时,我们发现了两种不同的行为,具体取决于是使用“真实”还是“模拟”数据库。

场景1:真实数据库

数据库中有5条记录:

db = realDatabase db.InsertOnSubmit(new record) var count1 = db.getTable.Count() db.SubmitChanges() var count2 = db.getTable.Count() 

count1 = 5 count2 = 6

场景2:模拟数据库

数据库中有5条记录:

 db= mockDatabase db.InsertOnSubmit(new record) var count1 = db.getTable.Count() db.SubmitChanges() var count2 = db.getTable.Count() 

count1 = 6 count2 = 6

*“模拟”数据库在调用SubmitChanges()之前已经知道新记录,因此它包含在计数中。 对于测试,我们需要两个行为相同。

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

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

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

我正在使用RhinoMocks,它看起来像这样:

 // arrange IList testdata = new List() {a, b, c}; db = MockRepository.GenerateMock(); db.Stub(x => db.getTable).Return(testdata); // act: call your unit under test // assert db.AssertWasCalled(x => x.InsertOnSubmit(Arg.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界面之后。 然后你模拟这个界面。

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