JCA
JCA

Reputation: 287

How to properly setup mock data for unit test?

Having some issues setting up my mock data for a unit test in my API. The data is retrieved from a service. Here is my endpoint and how the data is retrieved:

RetrieveExceptionReportSessionDatesResponse response
                    = await ResolveServiceClient().RetrieveExceptionReportSessionDatesAsync(new RetrieveExceptionReportSessionDatesRequest());

                List<ExceptionReportSessionDataModel> result
                    = GetSessionData(response.RetrieveExceptionReportSessionDatesResult);

                if (result != null && result.Count > 0)
                {
                    logText = LogFormatter.Format(
                                    WebUtilities.GetUser((ClaimsIdentity)HttpContext.User.Identity),
                                    startTime, DateTime.Now, Privilege.EditSession,
                                    "Get Exception Report Session Data", "Exception Report Session Data retrieved successfully.");
                    logger.LogInfo(logText);
                }
                else
                {
                    logText = LogFormatter.Format(
                                    WebUtilities.GetUser((ClaimsIdentity)HttpContext.User.Identity),
                                    startTime, DateTime.Now, Privilege.ViewOrderExceptionReport,
                                    "Get exception report session data", "Exception report session data is null or empty.");
                    logger.LogWarn(logText);
                }
                return Ok(result);

Here is what I have so far in setting up my unit test:

//Arrange          
            List<ExceptionReportSessionDataModel> sessionData = new List<ExceptionReportSessionDataModel>()
            { 
                new ExceptionReportSessionDataModel() {SessionName = "Session1", ReportFiles = null },
                new ExceptionReportSessionDataModel() {SessionName = "Session2", ReportFiles = null },
                new ExceptionReportSessionDataModel() {SessionName = "Session3", ReportFiles = null }
            };

            //NEED HELP HERE
            var ERSessionDataMock = new Mock<>();
            ERSessionDataMock.Setup(x => x.).Returns();

            var loggerMock = new Mock<ILogger>();
            loggerMock.Setup(x => x.LogInfo(null));

GetSessionData Method:

public List<ExceptionReportSessionDataModel> GetSessionData(string sessionData)
        {
            List<ExceptionReportSessionDataModel> reports = new List<ExceptionReportSessionDataModel>();
            if (!string.IsNullOrWhiteSpace(sessionData))
            {
                string[] splitString = sessionData.Split("\n", StringSplitOptions.RemoveEmptyEntries);

                foreach (string s in splitString)
                {
                    string[] temp = s.Split(",", StringSplitOptions.RemoveEmptyEntries);

                    List<string> files = new List<string>();

                    for (int index = 1; index < temp.Length; index++)
                    {
                        files.Add(temp[index]);
                    }
                    reports.Add(new ExceptionReportSessionDataModel()
                    {
                        ReportFiles = files,
                        SessionName = temp[0]
                    });
                }
            }
            return reports;
        }

I need help setting up the ERSessionDataMock

Upvotes: 2

Views: 998

Answers (1)

crgolden
crgolden

Reputation: 4614

It is impossible to know without seeing how the GetSessionData method is implemented. But here are some quick suggestions:

  1. Inject your ServiceClient as a dependency instead of calling a method to get it. It needs to either:

    • be an interface (like IServiceClient) - then in your Startup.cs class:
      services.AddScoped<IServiceClient>(sp => ResolveServiceClient().Result);
      
    • or the RetrieveExceptionReportSessionDatesAsync method needs to be virtual or abstract so you can override it with a mock:
      public virtual RetrieveExceptionReportSessionDatesAsync(RetrieveExceptionReportSessionDatesRequest request);
      
  2. Then in your test, create a response variable that will exercise the GetSessionData in a certain way to get either an empty List<ExceptionReportSessionDataModel> or not, depending on the test (again, no way to know exactly how without seeing your logic):

    var response = new RetrieveExceptionReportSessionDatesResponse();
    
  3. And override the RetrieveExceptionReportSessionDatesAsync method on the mock:
    var serviceClient = new Mock<IServiceClient>();
    serviceClient
        .Setup(x => x.RetrieveExceptionReportSessionDatesAsync(It.IsAny<RetrieveExceptionReportSessionDatesRequest>()))
        .Returns(response);
    
  4. Now, if you've setup response in a way that triggers GetSessionData to return a List<ExceptionReportSessionDataModel> that has Count > 0, you can verify that log message, otherwise verify the opposite log message.

But IMO, the way you've written this code makes unit testing a chore. You don't seem to be taking advantage of dependency injection.

UPDATE:

It seems you can either assign response as:

var response = new RetrieveExceptionReportSessionDatesResponse
{
    RetrieveExceptionReportSessionDatesResult = Guid.NewGuid().ToString()
}

and verify that logger.LogInfo is called with Privilege.EditSession, or assign response as:

var response = new RetrieveExceptionReportSessionDatesResponse
{
    RetrieveExceptionReportSessionDatesResult = string.Empty
}

and verify that logger.LogWarn is called with Privilege.ViewOrderExceptionReport.

Just one more observation - is there an off-by-one error in the for loop? (It is staring at index 1)

Upvotes: 1

Related Questions