简体   繁体   中英

How to use DbContext.Database in C# unit test cases using MOQ and Xunit

The problem statement looks lengthy but I have tried my best to make it as simple as possible.

I have a small function inside SchedulerLPOP10ReportDataView class which uses DbContext Object as:

public async Task<IEnumerable<T>> GetReportViewData<T>(OneFpsReportsDbContext dbContext)     
{
    var defaultTimeOut = dbContext.Database.GetCommandTimeout();
                            
    dbContext.Database.SetCommandTimeout(new TimeSpan(0,20,0));
    var results = await dbContext.VW_Report.FromSqlRaw($"SELECT * from [Analytics].[VW_LPOP10_Report_Scheduling]).ToListAsync();
    dbContext.Database.SetCommandTimeout(defaultTimeOut);
    return (IEnumerable<T>)(results);      
            
}

The OneFpsReportsDbContext class syntax looks like:

    public partial class OneFpsReportsDbContext : DbContext
    {
        public OneFpsReportsDbContext()
        {
        }
    
        public OneFpsReportsDbContext(DbContextOptions<OneFpsReportsDbContext> options)
            : base(options)
        {
        }
       //code
    }

I have written test case as:

[Fact]
public void GetReportViewData_OK()
{
    // Arrange
    
    var unitUnderTest = new SchedulerLPOP10ReportDataView(It.IsAny<int>());

    var mockSet = new Mock<DbSet<DbContext>>();
    var MockOneFpsReportsDbContext1 = new Mock<OneFpsReportsDbContext>();
    TimeSpan ts3 = TimeSpan.FromMinutes(20);
    MockOneFpsReportsDbContext1.Setup(x => x.Database.SetCommandTimeout(ts3)); //[1] error

    //Act
    var res = unitUnderTest.GetReportViewData<ISchedularReportDataView>(MockOneFpsReportsDbContext1.Object, WhereClause, sqlParameters).Result;

    //Assert
}

At [1] error I get this:

Unsupported expression: ... =>....SetCommandTimeout(ts3) Extension methods (here: RelationalDatabaseFacadeExtensions.SetCommandTimeout) may not be used in setup / verification expressions.

I also tried the 'UseInMemoryDatabase' approach but I came to know we can't use 'GetCommandTimeout' with it. What Am I missing or doing incorrect in the //Arrange section of my test case? And How exactly can I make this mock / work? Thanks.

This is, unfortunately, one of the hard-to-overcome limitations of XUnit/in-memory DB combo. You basically have two choices:

  • Spin up an actual test database locally for your unit testing purposes. In this case you'll be closer to production, but your test would kinda turn from unit into integration since you'll lack proper isolation

  • Create a wrapper class around the DbContext plus extension methods you need and mock that class instead.

The latter will look like this:

public class DbContextWrapper: OneFpsReportsDbContext
{
    public void SetCommandTimeout(TimeSpan ts)
    {
        this.Database.SetCommandTimeout(ts);
    }
}

// Then inside the usage block
public async Task<IEnumerable<T>> GetReportViewData<T>(DbContextWrapper dbContext)     
{
    var defaultTimeOut = dbContext.Database.GetCommandTimeout();
                            
    dbContext.SetCommandTimeout(new TimeSpan(0,20,0));
    var results = await dbContext.VW_Report.FromSqlRaw($"SELECT * from [Analytics].[VW_LPOP10_Report_Scheduling]").ToListAsync();
    dbContext.Database.SetCommandTimeout(defaultTimeOut);
    return (IEnumerable<T>)(results);                 
}

// And in the test:

[Fact]
public void GetReportViewData_OK()
{
    // Arrange
    
    var unitUnderTest = new SchedulerLPOP10ReportDataView(It.IsAny<int>());

    var mockSet = new Mock<DbSet<DbContext>>();
    var MockOneFpsReportsDbContext1 = new Mock<DbContextWrapper>();
    TimeSpan ts3 = TimeSpan.FromMinutes(20);
    MockOneFpsReportsDbContext1.Setup(x => x.SetCommandTimeout(ts3)); //[1] error

    //Act
    var res = unitUnderTest.GetReportViewData<ISchedularReportDataView>(MockOneFpsReportsDbContext1.Object, WhereClause, sqlParameters).Result;

    //Assert
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM