[英]Unit Testing practice with Linq to SQL
我试图将精力放在单元测试上,但是遇到了不确定的行为:
“可以备份库存”
基本上,“库存”表被复制到“库存历史”表,并给出备份发生时间的时间戳(“ HistoryDate”)。
这是备份库存的代码:
DateTime historyDate = DateTime.Now;
MyDataContext db = new MyDataContext();
db.GetTable<InventoryHistory>().InsertAllOnSubmit(
db.GetTable<Inventory>()
.Select(i => new InventoryHistory
{
ID = i.ID,
ItemName = i.ItemName,
/* etc, etc, etc */
HistoryDate = historyDate
})
);
我的问题是:
应该/可以将这种行为分解为较小的可单元测试的部分吗?
由于我正在针对专用的测试数据库进行测试,因此我是否应该使用模拟工具并遵循任何“存储库”的抽象工厂模式?
我要问的问题是,这真的是单元测试吗? 单元测试将考虑模拟的Table<TEntity>
实例,因为我们不关心实际数据,而是创建项目的机制是正确的。
在上面的代码段中,您似乎在对Linq方法本身进行单元测试,而不是自己编写的任何特定代码。
至于你的最后一个问题,用嘲讽取得了根本性的错误之一就是测试时,嘲讽的假设。 通常,您会嘲笑您要测试的类型所消耗的东西。 例如:
public ICalculatorService
{
int Add(int a, int b);
}
[Test]
public void CannAdd()
{
var mock = Mock<ICalculatorService();
mock.Setup(m => m.Add(It.IsAny<int>(), It.IsAny<int>()))
.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<ICalculatorService();
mock.Setup(m => m.Add(It.IsAny<int>(), It.IsAny<int>()))
.Returns(100);
var calculator = new Calculator(mock.Object);
Assert(calculator.Add(1, 2) == 100); // Correct
}
这更像它(尽管是一个简单的例子)。 我现在正在测试Calculator
使用者本身,而不是消耗品。 在您的示例中,即使您正在模拟DataContext以返回Table<TEntity>
虚拟实例,您还能获得什么真正的好处?
实际上,您可能会创建一个存储库,例如IInventoryRepository
,并创建该存储库的使用者(可以是域模型,控制器等)。 然后通过测试,您可以模拟该存储库,并测试您的使用者。
对我来说,这似乎是一项相当原子的操作,没有太多机会将其分解。
单元测试不会影响数据库-这是集成测试。 如果您要对此进行良好的单元测试,则可以测试行为-在这种情况下,应按原样备份历史记录。
通过全面披露,我才刚刚开始学习EF和LINQ以及测试它们的最佳方法,因此,您可能会获得有关它们的更多有用信息,因此,这些只是一般的测试答案。
1.除了以下方面,我看不到一种可以进一步细分以进行单元测试隔离的方法:
ID = i.ID,
ItemName = i.ItemName,
/* etc, etc, etc */
HistoryDate = historyDate
被重构为单独的方法以进行单元测试,因为只有LINQ调用是其他代码,MS负责测试。
2.我认为您无法引入接缝以将其与抽象存储库工厂模式隔离,因为您正在调用数据上下文。
我不确定您是否应该伪造此代码(由于您要对其进行测试将是一个模拟的正确方法-您对其进行测试的伪造品,而您未对其进行测试的伪造品是存根 ),但是由于它正在调用在测试服务器中,由于该功能涉及与数据存储的交互,因此您可以使其成为自动集成测试 。
首先,您描述的方法看起来很简单,但我不确定它是否需要任何单元测试。 但是,如果要分解,可以执行以下操作:
提取要备份的清单清单的提取方法
IQueryable GetInventoryForBackup(此DataContext上下文){return context.GetTable(); }
提取方法将库存转换为库存历史
IEnumerable ToInventoryHistory(此IEnumerable数据,DateTime historyDate){返回data.Select(i => new InventoryHistroy {ID = i.Id ....}
提取方法以保存InventoryHistory的顺序
SaveHistory(IEnumerable data){dataContext.InsertAllOnSubmit(data); dataContext.SubmitChanges(); }
现在您有了看似可行的方法,并且可以轻松编写单元测试。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.