Search code examples
c#.netunit-testingmoqxunit

Asserting void return type when testing


I have a class SchedulerLPOP10ReportDataView and inside this class I have a method AppendDateTimeFilter.

Please see the following snippet:

public class SchedulerLPOP10ReportDataView : IReportDataView,IDateRange
{
   public SchedulerLPOP10ReportDataView(int noOfPastDays)
   {
       CalculateStartDateAndEndDate(noOfPastDays);
   }

   public void AppendDateTimeFilter(StringBuilder preGeneratedWhereClause, DateTime startDateTime, DateTime endDateTime, List<SqlParameter> sqlParameters)
   {
       int count = sqlParameters.Count;
       string startDate = "@param" + (count).ToString();
       preGeneratedWhereClause.Append($" AND DATE BETWEEN " + startDate);
       sqlParameters.Add(new SqlParameter(startDate, System.Data.SqlDbType.Date));
       sqlParameters[count].Value = _startDateTime;
   }
}

I have written a test case to test this function as:

public void AppendDateTimeFilter_OK()
{
    // Arrange
    StringBuilder preGeneratedWhereClause = new StringBuilder("This is testing");
    DateTime startDateTime = DateTime.UtcNow;
    DateTime endDateTime = DateTime.UtcNow.AddSeconds(10);

    var indexIncrement = 0;
    var param = "@param" + indexIncrement.ToString();

    List<SqlParameter> sqlParameters = new List<SqlParameter>();            

    sqlParameters.Add(new SqlParameter(param, System.Data.SqlDbType.DateTime));

    var unitUnderTest = new SchedulerLPOP10ReportDataView(It.IsAny<int>()); //[1]

    //Act
    unitUnderTest.AppendDateTimeFilter(preGeneratedWhereClause, startDateTime, endDateTime, sqlParameters);

    //Assert
    //[2]
}

I read few articles about void return types mocking but didn't a get concrete answer. My doubts are as follows:

[1]: Is this statement correct? Can I call 'new SchedulerLPOP10ReportDataView' directly here or shall I even mock this class anyhow?. As of now this works just fine but is it a good approach?

[2]: Main doubt of this post. What do I assert here and How do I assert anything here as I don't have any return data because of 'AppendDateTimeFilter' being void.


Solution

  • var unitUnderTest = new SchedulerLPOP10ReportDataView(It.IsAny<int>()); 
    

    Can I call 'new SchedulerLPOP10ReportDataView' directly here or shall I even mock this class anyhow?

    Yes you can and should initialize the subject under test. There is no need to mock it in the test case.

    Is this statement correct?

    No. It.IsAny<int>() is meant to be used in expectation expressions when configuring a mock. Not as actual variable arguments when exercising test cases. Use an actual value.

    var unitUnderTest = new SchedulerLPOP10ReportDataView(0);
    

    What do I assert here and How do I assert anything here as I don't have any return data because of 'AppendDateTimeFilter' being void.

    Assert the expected behavior. The subject method under test modifies the injected query statement clause and the parameter collection. Assert what you would expect to happen to those variables after invoking the subject method.