使用 NUnit 对 DateTime 控制器进行单元测试

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


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在字符串中调用时,它不是当前的日期和时间?


慕仙森
浏览 85回答 1
1回答

慕村225694

实现此目的的常用方法是在您正在测试的对象的构造函数中注入日期/时间提供程序。例如:public interface IDateTimeProvider{&nbsp; &nbsp; DateTime Now();}以及该接口的具体实现:public class DateTimeProvider : IDateTimeProvider{&nbsp; &nbsp; public DateTime Now()&nbsp;&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; return Datetime.Now;&nbsp; &nbsp; }}您需要添加IDateTimeProvider到 DI 容器中,就像是services.AddSingleton<IDateTimeProvider, DateTimeProvider>();&nbsp;但这取决于你如何设置它,你正在使用哪个框架等。您的控制器将更改为如下所示:[Route ("api/[controller]")]public class DayTodayController : Controller{&nbsp; &nbsp; private readonly IDateTimeProvider _dateTimeProvider;&nbsp; &nbsp; public DayTodayController(IDateTimeProvider dateTimeProvider)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; _dateTimeProvider = dateTimeProvider;&nbsp; &nbsp; }&nbsp; &nbsp; [HttpGet, Route ("GetDate")]&nbsp; &nbsp; public&nbsp; string GetDate () {&nbsp; &nbsp; &nbsp; &nbsp; var dateTime = _dateTimeProvider.Now();&nbsp; &nbsp; &nbsp; &nbsp; var info = $"Today is {dateTime.ToString("dddd, dd MMMM yyyy")} and the time is {dateTime.ToString("hh:mm tt")}";&nbsp; &nbsp; &nbsp; &nbsp; return info;&nbsp; &nbsp; }}请注意将日期时间分配给变量。多次调用DateTime.Now将给出不同的值,因此您需要对一个实例进行操作以获得所需的行为。现在您可以使用该接口的非脆弱模拟实现进行测试:public class DayTodayTests{&nbsp; &nbsp; [Test]&nbsp; &nbsp; public void ReturnsDateAndTime()&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; //Arrange&nbsp; &nbsp; &nbsp; &nbsp; var mockedDateTimeProvider = new Mock<IDateTimeProvider>();&nbsp; &nbsp; &nbsp; &nbsp; mockedDateTimeProvider.Setup(dtp => dtp.Now()).Returns(new DateTime(2019, 8, 27, 10, 0, 0));&nbsp; &nbsp; &nbsp; &nbsp; var controller = new DayTodayController(mockedDateTimeProvider.Object);&nbsp; &nbsp; &nbsp; &nbsp; //Act&nbsp; &nbsp; &nbsp; &nbsp; string result = controller.GetDate();&nbsp; &nbsp; &nbsp; &nbsp; //Assert&nbsp; &nbsp; &nbsp; &nbsp; string expected = "Today is Tuesday 27 August 2019 and the time is 10:00 AM";&nbsp; &nbsp; &nbsp; &nbsp; Assert.AreEqual(expected, result);&nbsp;&nbsp; &nbsp; }}
打开App,查看更多内容
随时随地看视频慕课网APP