如何从单元测试中消除对数据库的依赖

How to eliminate the dependency on the database from a unit test

是否可以为此方法创建单元测试?

public void CheckIndicatorMeasurementRecordingValidity(IndicatorMeasurementRecording indicatorMeasurementRecording)
{
   var isDateRangeOverLapping = this.db.IndicatorMeasurementRecordingRepository.Any(r => r.IndicatorId == indicatorMeasurementRecording.Indicator.Id && r.Id != indicatorMeasurementRecording.Id
                && r.RecordingDateRange.ToDateTime >= indicatorMeasurementRecording.RecordingDateRange.FromDateTime
                && r.RecordingDateRange.FromDateTime <= indicatorMeasurementRecording.RecordingDateRange.ToDateTime);

   if (isDateRangeOverLapping)
   {
       throw new GrcUserException(IndicatorThresholdValidityManagementLocal.DateRangeOverlapping);
   }
}

我试过这样创建测试

[TestMethod]
public void Indicator_measurement_date_range_overlapping_shall_throw_exception()
{
    var indicator = new Indicator();
    var oldIndicatorMeasurementRecording = new IndicatorMeasurementRecording();
    var newIndicatorMeasurementRecording = new IndicatorMeasurementRecording();
    var errorMessage = string.Empty;

    oldIndicatorMeasurementRecording.Id = 1;
    oldIndicatorMeasurementRecording.RecordingDateRange.FromDateTime = DateTime.Today.AddDays(-5);
    oldIndicatorMeasurementRecording.RecordingDateRange.ToDateTime = DateTime.Today;
    indicator.IndicatorMeasurementRecordings.Add(oldIndicatorMeasurementRecording);

    oldIndicatorMeasurementRecording.Id = 2;
    newIndicatorMeasurementRecording.RecordingDateRange.FromDateTime = DateTime.Today.AddDays(-2);
    newIndicatorMeasurementRecording.RecordingDateRange.ToDateTime = DateTime.Today;
    newIndicatorMeasurementRecording.Indicator = indicator;

    try
    {
        this.indicatorValidityProxy.CheckIndicatorMeasurementRecordingValidity(newIndicatorMeasurementRecording);
    }
    catch (Exception ex)
    {
        errorMessage = ex.Message;
    }

    Assert.AreEqual(IndicatorThresholdValidityManagementLocal.DateRangeOverlapping, errorMessage);
}

问题是,测试总是失败,因为 this.db.IndicatorMeasurementRecordingRepository.Count 测试始终为 0。 出于开发目的,它总是 returns 正确的数字。只有在测试的时候是0.

谁能告诉我为什么 this.db.IndicatorMeasurementRecordingRepository.Count 用于测试目的总是 0?为我的案例编写测试的最佳实践是什么?

我不确定 the.db 是什么,但假设 public class MyContext : DbContextthis.dbMyContext 类型,那么使用 Mock 你可以:

var contextMock = new Mock<MyContext>();
// arrange more

本质上,当 IndicatorMeasurementRecordingRepository 被查询时,您会将 contextMock 配置为 return 一组已知的对象(IndicatorMeasurementRecording?)。类似于:

var dbSetMock = new Mock<IDbSet<DbEntity>>();
dbSetMock.Setup(m => m.Provider).Returns(data.Provider);
dbSetMock.Setup(m => m.Expression).Returns(data.Expression);
dbSetMock.Setup(m => m.ElementType).Returns(data.ElementType);
dbSetMock.Setup(m => m.GetEnumerator()).Returns(data.GetEnumerator());

var contextMock = new Mock<MyContext>();
contextMock 
    .Setup(x => x.DbEntities)
    .Returns(dbSetMock.Object);

其中数据是要从模拟中return编辑的对象列表。

一些可以帮助您的链接/示例:

我无法重新创建你的测试用例,因为那里没有太多代码,但如果你提供 mcve 我非常乐意更详细地查看测试。