c# – Linq to SQL的单元测试实践

我试图围绕单元测试,我遇到了一个我不确定的行为:

“可以备份库存”

基本上,“库存”表被复制到“InventoryHistory”表,并给出备份发生时的时间戳(“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

                })
        );

我的问题是:

>应该/可以将此行为分解为更小的可单元测试部件吗?
>由于我正在针对专用测试数据库进行测试,我是否应该使用模拟工具并遵循任何“存储库”的抽象工厂模式?

最佳答案 我要问的问题是,这真的是一个单元测试吗?单元测试将考虑模拟表< 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
}

这更像是它(虽然是一个简单的例子).我现在正在测试计算器消费者本身,而不是耗材.在您的示例中,即使您在模拟DataContext以返回Table< TEntity>的虚拟实例,您会获得什么真正的好处?

实际上你可能会创建一个存储库,例如一个IInventoryRepository,并创建该存储库的使用者(可以是域模型,控制器等).然后通过测试,您将模拟该存储库,并测试您的消费者.

点赞