首页 > 解决方案 > 为使用服务的端点编写单元测试时遇到问题,如何正确编写它?

问题描述

我没有编写端点或服务。我需要将此端点用于我正在构建的应用程序,并且我被要求在其上编写单元测试。我在正确编写测试时遇到了一些问题。这是我到目前为止的测试:

public void GetExceptionReportSessionData_ReturnsSessionData()
        {
            //Arrange 
            var response = new RetrieveExceptionReportSessionDatesResponse();
            var serviceClient = new Mock<WorkflowService.WorkflowService>();      
            serviceClient
                .Setup(x => x.RetrieveExceptionReportSessionDatesAsync(It.IsAny<RetrieveExceptionReportSessionDatesRequest>()))
               .ReturnsAsync(response);

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

            var controller = new ExceptionReportController(loggerMock.Object);

            var ctx = new ControllerContext() { HttpContext = new DefaultHttpContext() };
            ctx.HttpContext.Request.Headers["token"] = "fake_token_here"; //Set header
            controller.ControllerContext = ctx;

            //Act
            var result = controller.GetExceptionReportSessionData();

            //Assert
            var viewResult = Assert.IsType<OkObjectResult>(result);

            Assert.Equal(StatusCodes.Status200OK, viewResult.StatusCode);

        }

这是端点逻辑:

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);

这是端点中调用的 GetSessionData 方法:

private 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;
    }

如何完成编写成功的测试?

标签: c#unit-testingasp.net-coreasp.net-web-api

解决方案


您没有提供ResolveServiceClient()方法的定义。

按照以下步骤编写单元测试。

  1. 学习单元测试。这里没有笑话。在编写任何单元测试之前,您需要了解它的工作原理以及编写它们的原因。了解 SOLID 原则将有助于此过程。
  2. 分析 SUT 或您正在测试的方法并列出所有依赖项。外部依赖项是为您的方法执行某些任务的类。您正在测试当前方法,因此,不属于您的类的所有内容都需要解耦。换句话说,您不能对调用静态方法并在方法代码中初始化外部依赖项的类进行单元测试。在这里,在您的代码中LogFormatterWebUtilities它们似乎是静态类。
  3. 分析方法并记下所有退出点。例如返回语句、异常等。您必须为每个退出语句编写至少一个单元测试。
  4. 分析方法并记下所有 if-else 条件。您必须为每个条件编写一个单元测试。

除了所有理论之外,您的控制器似乎是一个简单的案例。在这里,如果LogFormatter没有抛出任何错误,那么您不必将其解耦。但WebUtility似乎有问题。因此,我建议为它创建一个服务并将其注入控制器中,以便您可以从单元测试中传递它的Mock 或 Stub

该方法没有任何问题,只需为每个条件GetSessions()编写案例即可。

这里有一个小提示,我尽量让控制器保持轻便。通常,我的控制器只是将 DTO 转换为服务 DTO 并调用服务。所以我不为控制器编写单元测试。但我不确定每个人都这样做。


推荐阅读