Search code examples
c#.netunit-testingasp.net-core-webapixunit

How to unit test nested method using xunit in .net core


I have below scenario

public long Update(ExpenseViewModel updateModel, string einterpriseid)
{
    long internId;
    ExpenseReq expenseRequest = GetReqById(updateModel.Id);
    if (expenseRequest != null)
    {
        int DraftStatusID = GetStatusID("Draft");
        int PendingStatusID = GetStatusID("Pending Approval");
    }
 }

 public ExpenseReq GetReqById(int id)
 {
    return _db.ExpRequest
            .Include(x => x.Profile).AsNoTracking()
            .Include(x => x.ExpReqStatus).AsNoTracking()
            .Include(x => x.AdditionalDetails)
            .ThenInclude(x => x.ExpenseReqTravelDetails).AsNoTracking()
            .Include(x => x.AddDetail)
            .ThenInclude(x => x.ExpRejReason).AsNoTracking()
            .Include(x => x.AdditionalDetails)
            .ThenInclude(x => x.ExpenseTypes).AsNoTracking()
            .Include(x => x.AdditionalDetails)
            .ThenInclude(x => x.ExpReqApprover).AsNoTracking()
            .Include(x => x.Comp).AsNoTracking()
            .Where(x => x.Id == id).FirstOrDefault();
 }

When I am performing unit test on Update the GetReqById function is always returning me null because of which the if condition is not getting satisfied and inside if condition line coverage is not happening. I want to get the code coverage inside if condition. How to write unit test for it? I have tried below:

[Fact]
public void Should_Update()
{
    var options = new DbContextOptionsBuilder<dbContextobj>().UseInMemoryDatabase(databaseName: "fakedb").Options;

    using (var context = new dbContextobj(options))
    { 
        var controller = new ExpenseRequestService(context);
        var result = controller.Update(expenseRequestUpdateViewModel, "test");
        Assert.Equal(0, result);
    }
}

This works fine but the GetReqById is not getting covered. Please help me with some sample code.

Thank you.

debug


Solution

  • You could setup the database with the required data:

    [Fact]
    public void Should_Update()
    {
        // Assign
        var options = new DbContextOptionsBuilder<dbContextobj>().UseInMemoryDatabase(databaseName: "fakedb").Options;
        using var context = new dbContextobj(options);
        context.ExpenseReq.Add(new ExpenseReq { Id = "test" })
        context.SaveChanges();
    
        var controller = new ExpenseRequestService(context);
    
        // Act
        var result = controller.Update(expenseRequestUpdateViewModel, "test");
    
        // Assert
        Assert.Equal(0, result);
    }
    

    However many will comment that this is not technically a unit test due to the use of the InMemoryDatabase.