c# - 使用 NUnit 对 DateTime Controller 进行单元测试

标签 c# unit-testing asp.net-core nunit moq

我正在创建一个 React/.NET Core 项目,其中一个页面显示当前日期和时间。我的 Controller 类如下:

namespace TestingReactDotNet.Controllers {

    [Route ("api/[controller]")]
    public class DayTodayController : Controller {

        [HttpGet, Route ("GetDate")]
        public  string GetDate () {

            var info = $"Today is {DateTime.Now.ToString("dddd, dd MMMM yyyy")} and the time is {DateTime.Now.ToString("hh:mm tt")}";
            return info;

        }
    }
}

我正在尝试对此进行单元测试并模拟日期和时间,但我正在努力做到这一点(我查看了其他 Stack Overflow 问题并进行了 Google 搜索,但我仍然遇到问题)。本来想用Moq,但是好像不行?

这是我目前的测试结果:

namespace TestingReactDotNetTests
{
    public class DayTodayTests
    {
        [Test]
        public void ReturnsDateAndTime()
        {
            var controller = new DayTodayController();
            string result = controller.GetDate();
            string expected = "Today is Tuesday 27 August 2019 and the time is 10:00";
            Assert.AreEqual(expected, result); 


        }
    }
}

我的问题是 - 如何设置日期和时间,以便在字符串中调用 DateTime.Now 时,它不是当前日期和时间?

最佳答案

实现此目的的常用方法是在您正在测试的对象的构造函数中注入(inject)一个日期/时间提供程序。例如:

public interface IDateTimeProvider
{
    DateTime Now();
}

以及该接口(interface)的具体实现:

public class DateTimeProvider : IDateTimeProvider
{
    public DateTime Now() 
    {
        return Datetime.Now;
    }
}

需要在DI容器中添加IDateTimeProvider

有点像

services.AddSingleton<IDateTimeProvider, DateTimeProvider>(); 

但这取决于您如何设置它,您使用的是哪个框架等。

你的 Controller 会变成这样:

[Route ("api/[controller]")]
public class DayTodayController : Controller
{
    private readonly IDateTimeProvider _dateTimeProvider;

    public DayTodayController(IDateTimeProvider dateTimeProvider)
    {
        _dateTimeProvider = dateTimeProvider;
    }

    [HttpGet, Route ("GetDate")]
    public  string GetDate () {
        var dateTime = _dateTimeProvider.Now();
        var info = $"Today is {dateTime.ToString("dddd, dd MMMM yyyy")} and the time is {dateTime.ToString("hh:mm tt")}";
        return info;
    }
}

注意将 DateTime 分配给变量。多次调用 DateTime.Now 会给出不同的值,因此您可能希望对一个实例进行操作以获得所需的行为。

现在您可以使用接口(interface)的非脆弱模拟实现进行测试:

public class DayTodayTests
{
    [Test]
    public void ReturnsDateAndTime()
    {
        //Arrange
        var mockedDateTimeProvider = new Mock<IDateTimeProvider>();
        mockedDateTimeProvider.Setup(dtp => dtp.Now()).Returns(new DateTime(2019, 8, 27, 10, 0, 0));
        var controller = new DayTodayController(mockedDateTimeProvider.Object);

        //Act
        string result = controller.GetDate();

        //Assert
        string expected = "Today is Tuesday 27 August 2019 and the time is 10:00 AM";

        Assert.AreEqual(expected, result); 
    }
}

关于c# - 使用 NUnit 对 DateTime Controller 进行单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57672373/

相关文章:

C# List.Find 方法 - 如何将值传递给谓词?

unit-testing - 如何编写需要大量测试用例的 go 测试

node.js - 单元测试 - 与 supertest 开 Jest 会超时

unit-testing - PHPUnit 中的模拟与 stub

c# - 如何使用服务用户凭据访问 Microsoft Graph 的服务

字符串的 C# 排列 n = ((n - 1) + (n - 2))

c# - 增加 Silverlight DataGrid 中的列宽以填充整个 DG 宽度

c# - 在计算机崩溃时调用 File.WriteAllText 会导致数据丢失

c# - .Net Core 中的 DbContextTransaction 在哪里

c# - Asp.Net Core Razor 页面,无法从其他 View /razor 模型访问 session 变量