Linq to SQL的unit testing实践
我试图围绕unit testing,我遇到了一个我不确定的行为:
“可以备份库存”
基本上,“库存”表被复制到“InventoryHistory”表,并给出备份发生的时间戳(“HistoryDate”)。
这是备份库存的代码:
DateTime historyDate = DateTime.Now; MyDataContext db = new MyDataContext(); db.GetTable().InsertAllOnSubmit( db.GetTable() .Select(i => new InventoryHistory { ID = i.ID, ItemName = i.ItemName, /* etc, etc, etc */ HistoryDate = historyDate }) );
我的问题是:
-
应该/可以将此行为分解为更小的可unit testing部件吗?
-
由于我正在测试专用测试数据库,我应该使用模拟工具并遵循任何“存储库”的抽象工厂模式吗?
我要问的问题是,这真的是一个unit testing吗? unit testing会考虑模拟Table
实例,因为我们不关心实际数据,而是创建项目的机制是正确的。
在上面的代码片段中,您似乎是自己unit testingLinq方法,而不是您自己编写的任何特定代码。
至于你的上一个问题,模拟的一个基本错误是假设在模拟时要测试什么。 通常,您会模拟要测试的类型所消耗的内容。 例如:
public ICalculatorService { int Add(int a, int b); } [Test] public void CannAdd() { var mock = Mock m.Add(It.IsAny(), It.IsAny ())) .Returns(100); var service = mock.Object; Assert(service.Add(1, 2) == 100); // Incorrect }
以上是一个毫无意义的测试,因为我正在测试它正在返回我告诉它的内容。 我不是在这里测试Moq框架,我需要测试我的代码,所以我需要测试消费者:
public class Calculator { private readonly ICalculatorService _service; public Calculator(ICalculatorService service) { _service = service; } public int Add(int a, int b) { return _service.Add(a, b); } } [Test] public void CannAdd() { var mock = Mock m.Add(It.IsAny(), It.IsAny ())) .Returns(100); var calculator = new Calculator(mock.Object); Assert(calculator.Add(1, 2) == 100); // Correct }
这更像是它(虽然是一个简单的例子)。 我现在正在测试Calculator
消费者本身,而不是耗材。 在您的示例中,即使您在模拟DataContext以返回Table
虚拟实例,您会获得什么真正的好处?
实际上,您可能会创建一个存储库,例如IInventoryRepository
,并创建该存储库的使用者(可能是域模型,控制器等)。 然后通过测试,您将模拟该存储库,并测试您的消费者。
对我来说这看起来像是一个相当primefaces的操作,没有多少机会将它分开。
unit testing不会影响数据库 – 即集成测试。 如果你想为此做一个好的unit testing,那么你将测试行为 – 在这种情况下,历史是在应该的时候备份的。
通过完全公开,我只是刚刚开始学习EF和LINQ以及测试它们的最佳方法,因此您可能会获得更多有关它们的有用信息,因此这些只是一般的测试答案。
1.除了以下方面,我无法看到一种可以进一步细分为unit testing的方法:
ID = i.ID, ItemName = i.ItemName, /* etc, etc, etc */ HistoryDate = historyDate
被重构为单独的方法进行unit testing,因为唯一的其他代码是LINQ调用,MS负责测试。
2.我认为您不能引入接缝来将其与抽象存储库工厂模式隔离,因为您正在调用datacontext。
我不确定你是否应该假装这个(因为你要对它进行测试将是一个模拟的正确 – 你测试的假,你没有测试的假是一个存根 )但是因为它正在调用在测试服务器中,您可以将其作为自动集成测试,因为该function涉及与数据存储的交互。
首先,您描述的方法看起来很简单,我不确定它是否需要任何unit testing。 但是,如果你想分解它,你可以这样做:
-
获取备份清单列表的提取方法
IQueryable GetInventoryForBackup(此DataContext上下文){return context.GetTable(); }
-
提取方法将Inventory转换为InventoryHistory
IEnumerable ToInventoryHistory(此IEnumerable数据,DateTime historyDate){return data.Select(i => new InventoryHistroy {ID = i.Id ….}
-
提取方法以保存InventoryHistory的序列
void SaveHistory(IEnumerable data){dataContext.InsertAllOnSubmit(data); dataContext.SubmitChanges(); }
现在你有了很好的方法,你可以轻松编写unit testing。
- System.ComponentModel.Win32Exception:操作成功完成
- 使用绑定填充路径数据属性时路径位置不正确
- RichTextBox中RTF文件中的超链接断开
- 如何使用与OnPropertyChanged一起使用的UserControl的可绑定属性
- 如何使用Ninject设置可选方法拦截?
- 如何将暴露给COM-interop的.NET对象标记为单线程?
- 检查系统DSN并创建系统DSN(如果不存在)(iSeries Access ODBC驱动程序)
- c#object.Dispose()或object = null
- 如何写入NUnit gui runner的Log选项卡和Console.Error选项卡