【问题标题】:How can I mock the following DBContext call being made using Moq for this C# code?如何模拟使用 Moq 对此 C# 代码进行的以下 DBContext 调用?
【发布时间】:2021-10-20 00:15:47
【问题描述】:

当在用 C# 编写的服务文件中遇到以下行时,我在使用 Moq 运行单元测试时遇到问题。任何关于如何模拟这个特定调用的有价值的输入都将在这里受到赞赏。谢谢。这里 _context 是 DBContext 的实例。

var dataObj = _context.FromSqlNotRequired(query, commandParameters).rows;

单元测试设置:

 private readonly Mock<P4IDBContext> _mockContext;
        private readonly Mock<DbSet<MetricsCalibrated>> _metricsCalibratedMockSet;
        private readonly Mock<DbSet<FilterResult>> _filterMockSet;   
        private readonly MetricsService _metricsService;
        private readonly Mock<IMetricsService> metricsService;
        private readonly Mock<Dictionary<String, String>> _dictionary;
        private readonly SourceDataController controller;

        //[Fact()]
        public MetricsServiceTests()
        {
            metricsService = new Mock<IMetricsService>();
           
            controller = new SourceDataController(metricsService.Object);
            _metricsCalibratedMockSet = new Mock<DbSet<MetricsCalibrated>>();
            _metricsCalibratedMockSet.Setup(m => m.AsQueryable()).Returns(_metricsCalibratedData);
            _dictionary = new Mock<Dictionary<String, String>>();
            _filterMockSet = new Mock<DbSet<FilterResult>>();
            _filterMockSet.Setup(m => m.AsQueryable()).Returns(_filterData);
            var commandParameters = new Dictionary<string, string>();
            _mockContext = new Mock<P4IDBContext>();
            
            _mockContext.Setup(m => m.MetricsCalibrated).Returns(_metricsCalibratedMockSet.Object);
            _mockContext.Setup(m => m.FilterResult).Returns(_filterMockSet.Object);
            _metricsService = new MetricsService(_mockContext.Object);

        }

错误 - 消息:

Message: 
    System.NullReferenceException : Object reference not set to an instance of an object.

  Stack Trace: 
    RelationalDatabaseFacadeExtensions.GetFacadeDependencies(DatabaseFacade databaseFacade)
    RelationalDatabaseFacadeExtensions.GetDbConnection(DatabaseFacade databaseFacade)
    DbContextExtensions.FromSqlNotRequired[T](DbContext context, String strSQL, Dictionary`2 commandParameters) line 24
    MetricsService.GetBasicData(String wherePart, IDictionary`2 selectedDict, String timeInterval, Dictionary`2 commandParameters, String tillDate) line 242
    MetricsService.GetFilteredData(FilterOptions options) line 64
    MetricsServiceTests.TestGetFilteredData() line 63

【问题讨论】:

  • 您是在测试SourceDataController 还是metricsService
  • 我正在测试metricsService。 public void TestGetFilteredData() { var result = this._metricsService.GetFilteredData(validFilterOptions); Assert.NotNull(result); }
  • 查看link
  • FromSqlNotRequired 是我不熟悉的扩展。你能分享一个指向定义它的代码/库的链接吗?如果它类似于内置的 FromSql 方法,那么模拟它可能会非常复杂
  • @rgvlee PFB 代码。 public static (List&lt;T&gt; rows, List&lt;string&gt; colNames) FromSqlNotRequired&lt;T&gt;(this DbContext context, string strSQL, Dictionary&lt;string, string&gt; commandParameters) where T : class { List&lt;T&gt; ret = new List&lt;T&gt;(); var columns = new List&lt;string&gt;(); ........ ............................................. return (ret, columns); }

标签: c# moq dbcontext xunit.net


【解决方案1】:
[Fact]
public void Test()
{ 
    //Below is the setup part. 
    //given  
    var metricsCalibratedData = new List<MetricsCalibrated>
        {
            new MetricsCalibrated{ /* ... */ }, /// fill sample data
            new MetricsCalibrated{ /* ... */ }
        }.AsQueryable();

        var mockMetricsCalibratedSet = new Mock<DbSet<MetricsCalibrated>>();
        mockMetricsCalibratedSet .As<IQueryable<MetricsCalibrated>>().Setup(m => m.Provider).Returns(metricsCalibratedData.Provider);
        mockMetricsCalibratedSet .As<IQueryable<MetricsCalibrated>>().Setup(m => m.Expression).Returns(metricsCalibratedData.Expression);
        mockMetricsCalibratedSet .As<IQueryable<MetricsCalibrated>>().Setup(m => m.ElementType).Returns(metricsCalibratedData.ElementType);
        mockMetricsCalibratedSet .As<IQueryable<MetricsCalibrated>>().Setup(m => m.GetEnumerator()).Returns(metricsCalibratedData.GetEnumerator());

   var filterResultData = new List<FilterResult>
    {
        new FilterResult{ /* ... */ },
        new FilterResult{ /* ... */}
    }.AsQueryable();

    var mockFilterResultSet = new Mock<DbSet<FilterResult>>();
    mockFilterResultSet.As<IQueryable<FilterResult>>().Setup(m => m.Provider).Returns(filterResultData .Provider);
    mockFilterResultSet.As<IQueryable<FilterResult>>().Setup(m => m.Expression).Returns(filterResultData .Expression);
    mockFilterResultSet.As<IQueryable<FilterResult>>().Setup(m => m.ElementType).Returns(filterResultData .ElementType);
    mockFilterResultSet.As<IQueryable<FilterResult>>().Setup(m => m.GetEnumerator()).Returns(filterResultData .GetEnumerator());

    var mockContext = new Mock<P4IDBContext>();
    mockContext.Setup(c => c.MetricsCalibrated).Returns(mockMetricsCalibratedSet.Object);
    mockContext.Setup(c => c.FilterResult).Returns(mockFilterResultSet.Object);

   var sut = new MetricsService(mockContext.Object);
  // Now, the test can b run

  var actualResult = sut.GetFilteredData(validFilterOptions);

  // Then Assert... 
  

【讨论】:

  • 在将上述代码与数据一起应用后,我仍然看到同样的问题。
  • 您是否在 Dbcontext 中将 DbSet&lt;MetricsCalibrated&gt; 声明为虚拟?
  • 是的,它被声明为虚拟的。这里的主要问题是以下行没有被嘲笑。模拟设置不应正确进入此方法并返回结果。我们如何防止这种情况发生? var dataObj = _context.FromSqlNotRequired(query, commandParameters).rows; 并且正在进入这个方法里面。在下一行的这个方法中,它给出了上面提到的异常。 using (var command = context.Database.GetDbConnection()
  • 不知道FromSqlNotRequired 方法,如果这是扩展方法,则无法模拟。
猜你喜欢
  • 1970-01-01
  • 2013-12-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-13
  • 2019-02-09
  • 2011-01-28
  • 2014-02-14
相关资源
最近更新 更多